【问题标题】:Java concurrently generate infinite amount of objectsJava同时生成无限数量的对象
【发布时间】:2014-01-12 16:49:10
【问题描述】:

所以我需要制作一个电梯模拟器,我想知道如何才能不断地让人们呼叫电梯。我需要这个永远持续下去。所以基本上一个人被创建并呼叫电梯。所有这些电话都会被跟踪,但我想我也需要跟踪实际在电梯上的人。

我有几门课PersonElevatorElevatorCall & ElevatorCallQueue

  1. In Person 我有一个 run() 方法,它基本上使用当前楼层和目标楼层进行电梯呼叫,然后我有一个 BlockingQueue 进行呼叫。此 run 方法仅在 true 时运行。

  2. ElevatorCall 我只有 getterssetters 用于收集和目标楼层

  3. 在 ElevatorCallQueue 中,我有 MAX_CALLS 和 numberOfPeople 的变量。 我有一个BlockingQueue<ElevatorCall> queue = new ArrayBlockingQueue<ElevatorCall>(MAX_CALLS)List<Person> 我将人员添加到列表中,然后遍历列表并在每个人上启动 run() 方法。最后,我创建了一个电梯并提供了队列,然后运行它。

  4. 在电梯里我有BlockingQueue<ElevatorCalls>。我在这里也有一个while(true),在其中我创建了一个ArrayList<ElevatorCall>,然后我使用BlockingQueues drainTo 方法,使用ArrayList<ElevatorCalls> 作为参数。 run() 方法的其余部分基本上遍历数组列表并执行电梯所做的工作,因此它会转到第一个按下的按钮,检查每个楼层是否有人以及是否是目标楼层。

现在我被卡住了,不知道从这里去哪里。我需要了解人们如何不断添加和呼叫电梯,如果没有更多呼叫,让电梯等待。如果有人能帮助我朝着正确的方向前进,我将不胜感激。 谢谢

编辑

Here is the code to the elevator class 有人说我应该发布一些代码。但是我不确定要发布什么代码,所以我想我应该把整个班级都放进去

【问题讨论】:

  • @SilviuBurcea 谢谢。我试着用词来表达更多的意思。我通常只显示我拥有的代码,但这可能会更好:) 有什么建议吗?
  • 您可能想尝试生产者/消费者模式。
  • 并发可能不是正确的工具,尤其是因为您需要以一定的速率同步生成与消耗。如果你不这样做,你可能很快就会溢出缓冲区,你的模拟结果取决于线程调度的随机性。在“模拟步骤”中工作并生成一些 + 消耗一些的简单循环将允许您逐步模拟。每一步都算作同一时间点,因此您在此处所做的所有事情都会对观察者“同时”发生。
  • 您可以为等待添加到您的模拟中的人添加一个大小有限的队列。将新人放在那里然后随机休眠一段时间的线程会产生他们。如果模拟不能及时消费,队列的大小限制可以防止人员溢出。电梯可以消耗每层排队的人。线程也可以等待条件,例如排队的人要等电梯到正确的楼层(人等电梯),电梯要等人进去,人再等正确的楼层出来。
  • 请注意,您的“呼叫队列”不应是队列。您按照通过它们的顺序服务楼层,而不是按按钮的顺序。您可能正在定义您的队列等,然后才能在脑海中明确定义模型。没有理由仅仅因为存在特定的数据类型就必须使用它。

标签: java multithreading concurrency wait


【解决方案1】:

我认为每个人都很快就接受了并发这个词——不要让它影响你的判断。我不能代表您的确切问题/标准发言,但电梯会前往楼层,唯一的干扰是新人按下按钮。那么,为什么不给电梯一个方法simulate(int time) 这样做,以及一个方法new_person(person p) 将另一个人添加到队列中。然后只需生成一个随机时间间隔,模拟电梯,添加一个随机楼层目的地和来源的新人,然后重复。

但你说它必须是并发的-

你的问题似乎是电梯呼叫来自哪里?

这是典型的生产者消费者模式的一个例子。你问什么? 好吧,BlockingQueue 的 oracle 文档提供了一个比我更好的例子

class Producer implements Runnable {
   private final BlockingQueue queue;
   Producer(BlockingQueue q) { queue = q; }
   public void run() {
     try {
       while (true) { queue.put(produce()); }
     } catch (InterruptedException ex) { ... handle ...}
   }
   Object produce() { ... }
 }

 class Consumer implements Runnable {
   private final BlockingQueue queue;
   Consumer(BlockingQueue q) { queue = q; }
   public void run() {
     try {
       while (true) { consume(queue.take()); }
     } catch (InterruptedException ex) { ... handle ...}
   }
   void consume(Object x) { ... }
 }

 class Setup {
   void main() {
     BlockingQueue q = new SomeQueueImplementation();
     Producer p = new Producer(q);
     Consumer c1 = new Consumer(q);
     Consumer c2 = new Consumer(q);
     new Thread(p).start();
     new Thread(c1).start();
     new Thread(c2).start();
   }
 }

嗯.. 你能看出这与你的问题有什么关系吗?你已经解决了一半。

电梯充当电梯呼叫的消费者,您似乎在为谁生产它们而苦苦挣扎。这是运行 ElevatorCall 生产者的新线程的工作。看看你能不能解决剩下的问题。

【讨论】:

  • 老实说,我只是回答了因为我看到了流行语“Java”和“并发”并认为很容易获得声誉:) Insta-upvote。非常欢迎您提供我能提供的任何帮助。
  • 我总是赞成任何花时间提供任何反馈的人 :) 问题出在并发模块中,因此它确实需要并发。我的 Elevator 类只接收从 ElevatorCallQueue 类发出的呼叫队列,因此 Elevator 不能真正添加​​新人。我不确定如何从另一个班级随机添加新人。
  • 我不会仔细研究逻辑——这里的并发只是增加了一个全新的复杂维度。但你无法避免它。 BlockingQueue 似乎就是它听起来的样子 - 你不能产生另一个线程来等待随机时间间隔将一个人添加到线程吗? Java 有一个同步的关键字可以帮助;)
  • 好吧,既然我已经承诺了,我现在将真正阅读您的代码;) - 通常您会在 main 中创建另一个线程,一条路径将执行电梯模拟,另一条路径将模拟人。它更...对称
猜你喜欢
  • 2017-02-12
  • 1970-01-01
  • 2018-04-15
  • 2012-03-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-08-18
  • 2015-09-04
相关资源
最近更新 更多