线程安全队列的模式/原则和;“船长/工人”;Java程序

线程安全队列的模式/原则和;“船长/工人”;Java程序,java,algorithm,multithreading,data-structures,queue,Java,Algorithm,Multithreading,Data Structures,Queue,我有一个问题,我相信这是典型的主/工作者模式,我正在寻求关于实现的建议。以下是我目前对这个问题的看法: 这里有一个某种形式的全局“队列”,它是保存“要完成的工作”的中心位置。大概这个队列将由一种“主”对象管理。线程将被生成以查找要做的工作,当它们找到要做的工作时,它们将告诉主对象(不管是什么)将其“添加到要完成的工作队列” 主线程可能会在一段时间内产生其他线程,实际执行要完成的工作。一旦一个线程完成了它的工作,我希望它通知主线程工作已经完成。然后,主机可以从队列中删除此工作 我过去用Java做过

我有一个问题,我相信这是典型的主/工作者模式,我正在寻求关于实现的建议。以下是我目前对这个问题的看法:

这里有一个某种形式的全局“队列”,它是保存“要完成的工作”的中心位置。大概这个队列将由一种“主”对象管理。线程将被生成以查找要做的工作,当它们找到要做的工作时,它们将告诉主对象(不管是什么)将其“添加到要完成的工作队列”

主线程可能会在一段时间内产生其他线程,实际执行要完成的工作。一旦一个线程完成了它的工作,我希望它通知主线程工作已经完成。然后,主机可以从队列中删除此工作

我过去用Java做过很多线程编程,但都是在JDK1.5之前,因此我不熟悉处理这种情况的合适的新API。我知道JDK7将有fork-join,这对我来说可能是一个解决方案,但我不能在这个项目中使用早期访问产品

在我看来,问题是:

1) 如何让“执行工作的线程”与主线程通信,告诉他们他们的工作已经完成,并且主线程现在可以从队列中删除工作

2) 如何有效地让master保证工作只安排一次。例如,假设这个队列有一百万个项目,它想告诉一个工人“去做这100件事”。什么是最有效的方式来保证当它将工作安排给下一个员工时,它得到的是“接下来的100件事”,而不是“我已经安排的100件事”

3) 为队列选择适当的数据结构。我在这里的想法是,“线程查找要做的工作”可能会发现同一个工作要做不止一次,并且它们会向主线程发送一条消息说“这里有工作”,主线程会意识到工作已经安排好,因此应该忽略该消息。我想确保我选择了正确的数据结构,这样计算就尽可能便宜

传统上,我会在数据库中以有限状态机的方式完成这项工作,从头到尾处理“任务”。然而,在这个问题中,我不想使用数据库,因为队列的容量和波动性都很高。另外,我希望这个尽量轻。如果可以避免的话,我不想使用任何应用服务器

我所描述的这个问题很可能是一个有着众所周知的名字和公认的解决方案的常见问题,但我,以我的非CS学位,不知道这叫什么(即,请温柔一点)

感谢您提供的所有提示。

请查看Java库

根据您的应用程序,它可能很简单,只需拼凑一些阻塞队列和ThreadPoolExecutor即可


此外,Brian Goetz的书可能会有所帮助。

首先,为什么要在工人开始做这些事情之后再拿着它们?通常,您会有一个工作队列,工作人员会从该队列中取出项目。这也将解决“如何防止员工获得相同物品”的问题

关于你的问题:

1) 如何让“线程”执行 工作“与船长沟通” 告诉他们他们的工作是 完成,大师现在可以 从队列中删除该工作

主人可以听工人们用键盘说话

2) 如何有效地获得硕士学位 保证工作是永远的 预定一次。比如说 此队列有一百万个项目,并且 想告诉工人“去做这些” 100件事”。什么是最有效的 当它 将工作安排给下一个工人,它 获取“接下来的100件事”而不是 “我已经做过的100件事 预定“

见上文。我会让工人们把物品从队列中拉出来

3) 选择合适的数据 队列的结构。我的想法 这里是“线程查找工作” “去做”可能会找到同样的结果 工作不止一次,他们会 给大师发个信,说 “这是工作”,大师会说 意识到工作已经完成 计划的,因此应该 忽略此消息。我想确保 我选择了正确的数据结构 因此,这种计算方法同样便宜 尽可能的


如果您对Spring的想法持开放态度,那么可以查看他们的Spring集成项目。它提供了所有开箱即用的队列/线程池样板,让您专注于业务逻辑。使用@annotations将配置保持在最低限度


顺便说一句,Goetz非常好。

据我所知,您需要。执行人服务

submit(Callable task)

返回值为的方法。未来是一种阻碍工人和主人之间沟通的方式。您可以轻松地扩展此机制,使其以异步方式工作。是的,ExecutorService也像ThreadPoolExecutor一样维护工作队列。因此,在大多数情况下,您不需要为日程安排而烦恼。java.util.concurrent包已经有了线程安全队列(ConcurrentLinkedQueue-nonblocking和LinkedBlockedQueue-blocking)的高效实现。

不要忘记Jini和Javaspaces。你所描述的听起来很像天基架构擅长的经典生产者/消费者模式

制作人将把这些工作写入空间。一个或多个消费者将(在一个事务下)取出作业并并行处理,然后将结果写回。由于该作业处于事务下,因此如果出现问题,则该作业将再次提供给客户