加油站模拟:如何模拟随机间隔开来的汽车?

发布于 2024-09-29 18:18:00 字数 636 浏览 4 评论 0原文

任务如下:

加油站由 2 个泵组成。每个泵都可以分配一定量的燃料。汽车以随机间隔到达并尝试使用两个泵之一:

- 如果泵可用并且有燃料,则汽车立即被允许使用它。每辆车都需要一定量的燃料(随机数),并且必须等待与该燃料量成比例的时间。例如,一辆车可能需要 6 加仑,将使用泵 3 秒,另一辆车可能需要 10 加仑,将使用泵 5 秒,等等。当汽车加满油时,它会离开,另一辆车可以使用泵。给汽车加油后,泵中的燃油量会相应调整。
- 如果两个泵当前都在使用,则到达的车辆将等待,直到两个泵之一可用。
- 如果泵耗尽燃料,则必须等待油轮提供更​​多燃料。油罐车定期到达(但不是太频繁),并将两个泵加满。当油罐车维修泵时,任何汽车都不能使用泵。 忘记添加此

第一部分:您必须提交符合上述规格的详细设计。您的设计必须使用 Java 线程。您必须指定要使用的线程数量和类型,以及如何同步这些线程。您可以用伪代码编写项目的此阶段。这是为了帮助您了解各个部分如何组合在一起。

第二部分:您必须使用 Java 线程和适当的同步方法提交设计的完整实现。您的实施必须根据上述规范仔细测试。


我想知道。如何使用 Java 线程来模拟以随机间隔进入的汽车?
我非常失落,感谢您提前提供的帮助。

The assignment is as follows:

The gas station consists of 2 pumps. Each pump has a certain amount of fuel it can distribute. Cars arrive at random intervals and attempt to use one of two pumps:

- If a pump is available and has fuel, the car is immediately allowed to use it. Each car requires a certain amount of fuel (random number), and has to wait for a time proportional to that amount of fuel. For example, a car may need 6 gallons and will use the pump for 3sec, another car may need 10 gallons and will use the pump 5 seconds, etc. When the car is fueled up, it leaves and the another car can use the pump. After fueling a car, the amount of fuel in the pump is adjusted accordingly.
- If both pumps are currently being used, then an arriving car waits until one of the two pumps becomes available.
- If a pump runs out of fuel, it must wait for a tanker to provide more fuel. The tanker arrives periodically (but not too often), and fills both pumps to capacity. While a tanker is servicing the pumps, no cars can use the pumps.
forgot to add this

Part I: you must submit a detailed design that matches the above specifications. Your design must use Java threads. You must specify how many and what type of threads you will be using, and how these threads will be synchronized. You can write this stage of the project in pseudo-code. This is to help you understand how the various pieces will together.

Part II: you must submit a complete implementation of your design using Java threads and appropriate synchronization methods. Your implementation must be carefully tested against the above specifications.

I want to know. How can I use a Java Thread to simulate the cars coming in at random intervals?

I am very lost and appreciate your help in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

偏爱你一生 2024-10-06 18:18:00

创建一个 Car 工厂类,该类生成要添加到出列的 Car 并随机休眠一段时间。

和所有学生一样,您可能会发现这个问题有点难以解决。如果你不开始把它分解成你可以处理的更小的块。考虑一个整体设计并开始实施其中的小部分。

例如,这是一个排队论问题。他们可以是汽车、银行排队的人,或者任何与队列互动的东西。不用担心汽车或加油站的详细信息。这是您的问题:

  1. 您有一行在一端添加新条目并在另一端删除它们。它称为出队数据结构。仔细阅读一下。看看您是否可以编写(或重用)Java Dequeue 类。彻底明白了。编写一个小驱动程序以添加到一端并从另一端删除。
  2. 一旦完成,您需要编写类来创建新条目以添加到出队中,并创建另一个类以将它们删除。只需编写以固定间隔工作的加法器/除法器即可开始。你应该看到的是,如果加法器和移除器具有完全相同的接口,则排队等待的条目数不会改变。如果加法器的工作速度比去除器快,则该行应该填满。如果删除器比加法器工作得更快,您将永远不会有备份。确保您的简单类表现出这种行为。
  3. 添加随机位并开始模拟。您需要查看队列中的条目数如何随时间变化。
  4. 现在添加不止一行。您想了解添加更多线路如何改变动态。

Create a Car factory class that spits out a Car to be added to a dequeue and goes to sleep for a random period of time.

Like all students, you're probably finding this problem to be a little overwhelming. It is if you don't start breaking it down into smaller chunks that you can handle. Think of an overall design and start implementing small pieces of it.

For example, this is a queuing theory problem. They could be cars, people in bank lines, or anything interacting with a queue. Don't worry about the cars or the gas station details. Here's your issue:

  1. You've got a line that adds new entries at one end and takes them off at the other. It's called a dequeue data structure. Read up on that. See if you can write (or reuse) a Java Dequeue class. Understand it completely. Write a small driver to add to one end and remove from the other.
  2. Once you have that, you need to write classes that create new entries to add to the dequeue and another to remove them. Start simply by writing adders/removers that work at a fixed interval. What you should see is that if the adder and remover have exactly the same interface, the number of entries waiting in line will not change. If the adder works faster than the remover, the line should fill up. If the remover works faster than the adder, you'll never have a backup. Make sure that your simple classes exhibit this kind of behavior.
  3. Add in the random bits and start your simulation. You'll want to see how the number of entries in line changes over time.
  4. Now add more than one line. You want to see how adding more lines changes the dynamics.
平安喜乐 2024-10-06 18:18:00

如果您有固定的间隔,则在该间隔内到达的汽车数量呈泊松分布。

两辆车之间的时间间隔的概率密度与 exp(-t/tau) 成正比,其中 tau 描述了汽车到达的频率。因此,您需要弄清楚如何创建指数分布的随机数。

根据概率密度 p(t)=c*exp(-t/tau),我们对累积概率分布 P(t)=1-exp(-t/tau) 进行积分。因此,反转该函数,您将得到 t=-tau*ln(1-P(t))。因此,如果生成一个在 0 和 1 之间均匀分布的数字 u,则可以获得正确分布的 t,如 t=-tau*ln(1-u)

If you have fixed intervals the number of cars arriving in that interval is Poisson distributed.

The time between two cars has a probabilitydensity proportional to exp(-t/tau) where tau describes the frequency of cars arriving. So you need to figure out how to create exponentially distributed random numbers.

From a probability density of p(t)=c*exp(-t/tau) we integrate a cumulative probability distribution of P(t)=1-exp(-t/tau). So inverting that function you get t=-tau*ln(1-P(t)). So if you generate a number u uniformly distributed between 0 and 1 you can get a correctly distributed t as t=-tau*ln(1-u)

沙与沫 2024-10-06 18:18:00

我可以看到你要使用线程去哪里,但你并不真正需要线程,除非这是一个图形模拟,你希望人们看到它实时运行。否则,只需跟踪时间表即可。了解在任何给定时间点接下来将发生什么事件:
A) 卡车到达。
B) 汽车到达。
C) 汽车离开。

我想您正在跟踪这些事情需要多长时间,因此只需模拟事件更快地发生即可。每次一辆车到达时,新车到达所需的时间将是由您决定的随机时间。

相信我,简单的事情会让你的生活变得更加轻松。

I can see where you're going with a thread, but you don't really need one unless this is a graphic simulation in which you wish people to see it run in real time. Otherwise, simply keep track of a timeline. Know at any given point in time what event is going to happen next between:
A) Truck arrives.
B) Car arrives.
C) Car leaves.

I imagine you're keeping track of how long these things take, so simply simulate the event to happen sooner. And everytime a car arrives, the time it takes for a new car to arrive will be a random amount of time decided by you.

Trust me, it'll make life a lot easier for you to simply things.

池木 2024-10-06 18:18:00

首先,由于您的 OP 和问题陈述中都没有任何内容表明系统正在按照挂钟运行,因此不要假设它确实如此。任何基于在制造汽车之间休眠十秒的东西都会让你在测试时发疯。创建一个简单的界面来为模拟提供时间并针对该模拟进行工作;如果您需要将其连接到挂钟,那么您可以,但您也可以按照机器的运行速度运行测试。

其次,通常最好在事件发生时运行模拟 - 汽车到达车站、汽车从队列过渡到泵、汽车离开泵、油罐车到达。通常,基于事件时间的事件优先级队列是有效的;当汽车开始加油时,您可以将其完成任务的事件添加到带有未来时间戳的事件队列中。如果在给定时间有油轮的话,编写不处理汽车的逻辑比搞乱线程优先级要容易得多。

由于您的任务要求您演示线程之间的某种同步,因此您可能希望将汽车等待、汽车加油/油罐车卸载等进程作为单独的线程运行(在实际软件中您不会,但更可能使用 futures 和执行器,如果您想要并行执行,但我假设这是一项教学任务,您需要展示一些线程设计,而不是让库为您整理所有内容)。

因此,对于每个时间片,您处理队列中的事件,等待所有事件处理完成,然后向时钟询问下一个时钟周期。快时钟将立即返回下一秒的时间戳,或者挂钟时钟将等到系统时间的下一秒。

由于每个任务都需要使用线程,因此需要在每个时间片的开始和结束时同步这些任务,并且需要同步或以其他方式确保排队的事件在时间片结束之前安全地排队并可见。

所以任务类似于:

  • 传入的汽车

    • 每秒确定汽车到达的数量。这将是泊松分布。
    • 对于每次到达,发布汽车到达事件(或发布包含汽车数量的事件)
      (或者,使用其他一些随机机制;大多数其他方法只会导致一辆车一次到达,这通常不是对模型施加有用的限制)
  • 传入油轮

    • 每台泵发生油轮到达事件后的每个(油轮到达周期)
  • 等待车辆

    • 增加汽车到达事件中等待的汽车数量
    • 如果油轮已抵达,设置油轮等待标志
    • 如果泵空闲,那么
      • 如果油轮正在等待,请重置油轮等待标志、加注泵、后泵空闲事件,以便将来加注泵的时间
      • 如果泵有燃料并且有任何汽车正在等待,则减少等待的汽车数量,并在未来为汽车加油时发布泵免费事件

问题陈述不清楚油罐车是否必须等待两个泵都空闲才能开始加注,在这种情况下,您需要添加另一个'油轮准备就绪状态。

如果任务位于不同的线程中,则需要“手动”或使用 java.util.concurrent.atomic 中的原子值来同步各个计数器。

Firstly, as there is nothing in either your OP nor the extra bit of the problem statement which states that the system is operating against the wall clock, don't assume it does. Anything based on Sleeping for ten seconds between creating cars will drive you crazy while you're testing it. Create a simple interface to provide time for the simulation and work against that; if you need to tie it to the wall clock then you can, but you can also run your tests as fast as your machine will go.

Secondly, it's usually better to run simulations as events - car arrives at station, cars transitions from queue to pump, car leaves pump, tanker arrives. Usually a priority queue of events based on their times works; when a car starts filling, you add the event for it completing its task to the event queue with a timestamp in the future. It's much, much easier to write logic not to process cars if there is a tanker at a given time than to mess around with threading priorities.

Since your task requires that you demonstrate some synchronisation between threads, you might want to run the processes of cars waiting, cars filling/tankers unloading as separate threads ( in real software you wouldn't, but more likely use futures and an executor if you wanted parallel execution, but I'm assuming this is a pedagogic task and you need to show some design of threads, rather than letting the library sort it all out for you ).

So for each time slice, you process the events from the queue, wait for all event processing to complete, and then ask the clock for the next tick. The fast clock will immediately return a timestamp for the next second, or a wall clock clock would wait until the next second of the system time.

Since you're required to use threads for each task, you need to synchronise these tasks at the start and end of each time slice, and you need to synchronise or otherwise ensure that enqueued events are safely enqueued and visible before a time slice finishes.

So the tasks are something like:

  • incoming cars

    • every second, determine the number of car arrivals. this will be a Poisson distribution.
    • for each arrival, post a car arrived event ( or post an event with the number of cars)
      (alternatively, use some other random mechanism; most of the other approaches will only cause one car to arrive at a time, which is not often a useful restriction to place on a model)
  • incoming tankers

    • every (tanker arrival period) post a tanker arrived event per pump
  • waiting cars

    • increment the number of cars waiting on car arrival event
  • pumps

    • if a tanker has arrived, set the tanker waiting flag
    • if the pump is free, then
      • if a tanker is waiting, reset the tanker waiting flag, fill pump, post pump free event for time-to-fill-pumps in future
      • if the pump has fuel and any car is waiting, decrement the cars waiting count, post pump free event for time-to-fill-car in future

The problem statement isn't clear whether the tanker has to wait for both pumps to be free before it can start filling them, in which case you would need to add another 'tanker ready' state.

If the tasks are in different threads, you would need to synchronise the various counters, either 'manually' or by using the atomic values in java.util.concurrent.atomic.

初懵 2024-10-06 18:18:00

您可以使用同类汽车源。您可以建立一些时间间隔,例如具有随机偏差的时间间隔。

You can use same kind of cars source. You can establish some time interval for example with random deviation.

北城半夏 2024-10-06 18:18:00

您可以使用线程安全的 PriorityBlockingQueue 创建事件队列。

基本上,汽车到达、油罐车到达、汽车进入泵和汽车离开泵都是事件。每个事件都有一个发生顺序,您可以为每个事件插入一个带有时间戳的“事件”对象。您可以进行安排,以便 PriorityBlockingQueue 使用时间戳对事件进行排序。

最初,您为汽车到达生产者线程和油轮到达生产者线程启动一个线程。汽车到达线程会将 CarArrivalEvent put() 放入队列中,然后休眠一段随机时间。油轮线程也执行相同的操作,但使用的是 put() TankerArrivalEvent。

加油站有两个泵,每个泵都由消费者线程表示。每个泵线程都会 take() 一个 CarArrivalEvent,然后休眠一段时间来填充汽车。您对 TankerArrivalEvent 执行类似的操作。

You can use the thread-safe PriorityBlockingQueue to create an event queue.

Basically, car arrivals, tanker arrivals, car entering pump, and car exiting a pump are all events. Each of these have an order of occurrence, you insert an "Event" object for each of these events, with a timestamp. You can arrange so that the timestamp is used by the PriorityBlockingQueue to sort the events.

Initially, you start a thread for the car arrival producer thread and tanker arrival producer thread. The car arrival thread will put() a CarArrivalEvent to the queue, and then sleep for an random amount of time. The tanker thread also does the same, but put() TankerArrivalEvent instead.

The gas station has two pumps, each represented by consumer threads. Each pump thread will take() a CarArrivalEvent, then sleep for the amount of time needed to fill the car. You do similarly for TankerArrivalEvent.

北城孤痞 2024-10-06 18:18:00

不要使用泊松分布。泊松将为您提供“接下来 X 分钟内到达的人数”。它不会给您“下次到达前的时间”。

像这样编写一个小 while 循环 ::

  public int getTimeTillNextCar() {
    PROBABILITY = .001;
    int timeTillNextCar = 0;
    while(rand.nextDouble() > PROBABILITY) {
      timeTillNextCar++;
    }
  }

显然,我只是假设您正在使用谨慎的时间。然而,使用指数中的单次抽取是可能的(有些人认为更好)。这样会更有效率。然而,使用这种方法会使代码变得“数学”,有些人可能不喜欢/理解。

请记住,泊松分布是通过计算当 p 非常小且 n 适度大时给定 n 次抽签成功的伯努利抽签次数得出的。如果 n “太大”,那么 Possion 分布将收敛到正态分布。

至于设计的其余部分...

Thread_A 应该将汽车添加到队列中(确保使用线程安全队列类)

Thread_A 应该这样做:
添加汽车,
睡眠(getTimeTillNextCar()),
添加汽车,
睡眠(getTimeTillNextCar()),
添加汽车,
睡眠(getTimeTillNextCar()),
等等......

Thread_B 和 Thread_C 应该将汽车从队列中取出:
Thread_B(和C)应该这样做:
get_car_off_queue,
睡眠(car.getFuelingTime(),
get_car_off_queue,
睡眠(car.getFuelingTime(),
ETC...

Don't Use a Poisson Distribution. Poission will give you "Number arrivals in next X minutes." It will not give you "Time until next arrival".

Wite a small while loop like so ::

  public int getTimeTillNextCar() {
    PROBABILITY = .001;
    int timeTillNextCar = 0;
    while(rand.nextDouble() > PROBABILITY) {
      timeTillNextCar++;
    }
  }

Obviously, I just assumed you are using discreet time. However, it is possible (and some would argue better) to use a single draw from an exponential. This will be more efficent. However, using that approach makes the code "mathy" which some people might not like/understand.

Remeber, the Poisson distribution arrives from counting how many bernoulli draws were succesful given n draws when p is very small and n is moderately big. If n is "too" big then the Possion distribution will converge to the Normal distribution.

As for the rest of the design...

Thread_A should add cars to a Queue (be sure to use a thread safe queue class)

Thread_A shoule do this:
add car,
sleep(getTimeTillNextCar()),
add car,
sleep(getTimeTillNextCar()),
add car,
sleep(getTimeTillNextCar()),
etc....

Thread_B and Thread_C should take cars off the queue:
Thread_B (and C) should do this:
get_car_off_queue,
sleep(car.getFuelingTime(),
get_car_off_queue,
sleep(car.getFuelingTime(),
etc...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文