作业如下:
加油站由2个泵组成。每个泵都有一定量的燃料可以分配。汽车随机到达,并尝试使用两个泵中的一个:
- 如果有泵并且有燃料,则可立即允许汽车使用它。每辆车都需要一定量的燃料(随机数),并且必须等待与该燃料量成比例的时间。例如,一辆汽车可能需要6加仑并且将使用泵3秒,另一辆汽车可能需要10加仑并且将使用泵5秒等。当汽车加油时,它离开而另一辆车可以使用泵。在为汽车加油后,泵中的燃油量也会相应调整 - 如果当前正在使用两个泵,那么到达的汽车将等待,直到两个泵中的一个变为可用 - 如果泵的燃料耗尽,它必须等待油轮提供更多燃料。油轮定期到达(但不是经常),并将两个泵填满容量。当油轮为泵提供服务时,没有汽车可以使用泵。 忘记添加此
第一部分:您必须提交符合上述规格的详细设计。您的设计必须使用Java线程。您必须指定将使用的线程数量和类型,以及这些线程的同步方式。您可以用伪代码编写项目的这个阶段。这是为了帮助您了解各个部分将如何组合在一起。
第二部分:您必须使用Java线程和适当的同步方法提交完整的设计实现。必须根据上述规范仔细测试您的实施。
我想知道。如何使用Java Thread来模拟随机进入的汽车?
我很失落,并提前感谢你的帮助。
答案 0 :(得分:12)
创建一个Car工厂类,该工厂类将一个Car添加到一个dequeue并随机进入休眠状态。
像所有学生一样,你可能会发现这个问题有点压倒性。如果你没有开始将它分解成你可以处理的较小块。想一想整体设计并开始实现它的一小部分。
例如,这是一个排队论问题。它们可能是汽车,银行行中的人,或与队列交互的任何东西。不要担心汽车或加油站的细节。这是你的问题:
答案 1 :(得分:3)
如果您有固定的间隔,则在该间隔内到达的汽车数量为Poisson。
两辆车之间的时间概率密度与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)
答案 2 :(得分:1)
我可以看到你在哪里使用一个线程,但你真的不需要一个,除非这是一个图形模拟,你希望人们看到它实时运行。否则,只需跟踪时间表即可。在任何给定的时间点知道接下来会发生什么事件: A)卡车到达。 B)汽车到达。 C)汽车离开。
我想你会记录这些事情花了多长时间,所以简单地模拟事件发生得更快。每次有车到达时,新车到达的时间将是您决定的随机时间。
相信我,它会让你的生活变得更容易。
答案 3 :(得分:1)
首先,由于你的OP或问题陈述中没有任何内容表明系统是在挂钟上运行,所以不要假设它。任何基于睡眠的东西在创建汽车之间持续十秒都会让你在测试时发疯。创建一个简单的界面,为模拟提供时间并对其进行操作;如果您需要将它连接到挂钟,那么您可以,但您也可以像机器一样快地运行测试。
其次,通常最好将模拟作为事件运行 - 汽车到达车站,汽车从排队过渡到泵,汽车离开泵,油轮到达。通常基于时间的事件的优先级队列工作;当汽车开始填充时,您将完成其任务的事件添加到事件队列中,并在将来添加时间戳。如果在给定时间有油轮而不是处理线程优先级,那么编写逻辑不会处理汽车要容易得多。
由于你的任务要求你在线程之间展示一些同步,你可能想要运行汽车等待的过程,汽车加油/油轮卸载作为单独的线程(在真实软件中你不会,但更可能使用期货和执行程序,如果你想要并行执行,但我认为这是一个教学任务,你需要展示一些线程设计,而不是让图书馆为你排序所有。)
因此,对于每个时间片,您处理队列中的事件,等待所有事件处理完成,然后询问时钟以进行下一次滴答。快速时钟将立即返回下一秒的时间戳,或挂钟时钟将等到系统时间的下一秒。
由于您需要为每个任务使用线程,因此您需要在每个时间片的开始和结束时同步这些任务,并且您需要同步或以其他方式确保排队的事件在一段时间之前安全地排队并可见切片完成。
所以任务就像:
来车
来货油轮
等车
泵
问题陈述尚不清楚油轮是否必须等待两个泵自由才能开始填充它们,在这种情况下你需要增加另一个“油罐就绪”状态。
如果任务在不同的线程中,则需要“手动”或使用java.util.concurrent.atomic中的原子值来同步各种计数器。
答案 4 :(得分:0)
您可以使用相同类型的汽车来源。您可以建立一些时间间隔,例如随机偏差。
答案 5 :(得分:0)
您可以使用线程安全的PriorityBlockingQueue来创建事件队列。
基本上,汽车到达,油罐车到达,汽车进入泵,以及离开泵的汽车都是事件。其中每个都有一个出现顺序,您为每个事件插入一个“事件”对象,并带有时间戳。您可以进行排列,以便PriorityBlockingQueue使用时间戳对事件进行排序。
最初,您为汽车到达生产者线程和油轮到达生产者线程启动一个线程。汽车到达线程将put()
一个CarArrivalEvent发送到队列,然后休眠一段随机时间。油轮螺纹也是这样,但put()
TankerArrivalEvent代替。
加油站有两个泵,每个泵由消费者线程代表。每个泵线程将take()
一个CarArrivalEvent,然后休眠一段时间来填充汽车。你对TankerArrivalEvent做了类似的事情。
答案 6 :(得分:0)
不要使用泊松分布。 Poission将为您提供“在接下来的X分钟内到达的号码”。它不会给你“下次到达的时间”。
Wite a while while while like ::
public int getTimeTillNextCar() {
PROBABILITY = .001;
int timeTillNextCar = 0;
while(rand.nextDouble() > PROBABILITY) {
timeTillNextCar++;
}
}
显然,我只是假设你正在使用谨慎的时间。但是,使用指数的单一绘制是可能的(并且有些人会更好)。这样会更有效率。但是,使用这种方法会使代码“混乱”,有些人可能不喜欢/理解。
记住,Poisson分布是通过计算当p非常小并且n中等大时给定n个绘制成功的伯努利数量而得出的。如果n“太大”,那么Possion分布将收敛到正态分布。
至于设计的其余部分......
Thread_A应该将汽车添加到队列中(确保使用线程安全队列类)
Thread_A shoule这样做:
加车,
睡眠(getTimeTillNextCar()),
加车,
睡眠(getTimeTillNextCar()),
加车,
睡眠(getTimeTillNextCar()),
等....
Thread_B和Thread_C应该将汽车从队列中取出:
Thread_B(和C)应该这样做:
get_car_off_queue,
睡眠(car.getFuelingTime(),
get_car_off_queue,
睡眠(car.getFuelingTime(),
等...