Java 从多个队列中消费
我有大量的状态机。有时,状态机需要从一个状态移动到另一个状态,这可能是便宜的,也可能是昂贵的,并且可能涉及数据库读写等 这些状态更改是由于来自客户端的传入命令而发生的,并且可以随时发生 我想将工作量并行化。我想要一个队列,上面写着“将这台机器从这个状态移动到这个状态”。显然,任何一台机器的命令都需要按顺序执行,但是如果我有许多线程,我可以并行地向前移动许多机器 每个状态机可以有一个线程,但状态机的数量取决于数据,可能有数百或数千个线程;我不想要每个状态机都有一个专用线程,我想要某种类型的池 我如何拥有一个工作线程池,但确保严格按顺序处理每个状态机的命令Java 从多个队列中消费,java,concurrency,Java,Concurrency,我有大量的状态机。有时,状态机需要从一个状态移动到另一个状态,这可能是便宜的,也可能是昂贵的,并且可能涉及数据库读写等 这些状态更改是由于来自客户端的传入命令而发生的,并且可以随时发生 我想将工作量并行化。我想要一个队列,上面写着“将这台机器从这个状态移动到这个状态”。显然,任何一台机器的命令都需要按顺序执行,但是如果我有许多线程,我可以并行地向前移动许多机器 每个状态机可以有一个线程,但状态机的数量取决于数据,可能有数百或数千个线程;我不想要每个状态机都有一个专用线程,我想要某种类型的池 我如
更新:假设
机器
实例有一个未完成命令列表。当线程池中的执行器使用完一个命令后,如果它有更多未执行的命令,它会将机器
放回线程池的任务队列中。所以问题是,当您附加第一个命令时,如何自动地将机器
放入线程池?并确保这一切都是线程安全的?我建议您使用以下方案:
执行器的固定大小的线程池。newFixedThreadPool
HashMap
),为每个状态机保存一个信号量。该信号量的值为1,并且将是公平的信号量以保持序列
semaphore.aquire()
,并在run方法的末尾添加semaphore.release()
通过线程池的大小,您可以控制并行级别。我建议您使用以下方案:
执行器的固定大小的线程池。newFixedThreadPool
HashMap
),为每个状态机保存一个信号量。该信号量的值为1,并且将是公平的信号量以保持序列
semaphore.aquire()
,并在run方法的末尾添加semaphore.release()
通过线程池的大小,您可以控制并行度。我建议另一种方法。不要使用线程池来移动状态机中的状态,而是将线程池用于所有操作,包括执行工作。在完成导致状态更改的某些工作后,应将状态更改事件添加到队列中。处理状态更改后,应将另一个do work事件添加到队列中 假设状态转换是工作驱动的,反之亦然,则不可能进行顺序处理 将信号量存储在特殊映射中的想法是非常危险的。映射必须同步(添加/删除obj是线程不安全的),并且执行搜索(可能在映射上同步)然后使用信号量的开销相对较大
此外,如果您想在应用程序中使用多线程体系结构,我认为您应该一直这样做。混合不同的体系结构可能会避免以后的麻烦。我建议另一种方法。不要使用线程池来移动状态机中的状态,而是将线程池用于所有操作,包括执行工作。在完成导致状态更改的某些工作后,应将状态更改事件添加到队列中。处理状态更改后,应将另一个do work事件添加到队列中 假设状态转换是工作驱动的,反之亦然,则不可能进行顺序处理 将信号量存储在特殊映射中的想法是非常危险的。映射必须同步(添加/删除obj是线程不安全的),并且执行搜索(可能在映射上同步)然后使用信号量的开销相对较大
此外,如果您想在应用程序中使用多线程体系结构,我认为您应该一直这样做。混合使用不同的体系结构可以避免以后的麻烦。为每台机器提供一个线程ID。生成所需数量的线程。让所有线程贪婪地处理来自全局队列的消息。每个线程都将当前消息的服务器锁定为自己独占使用(直到它处理完当前消息及其队列上的所有消息为止),其他线程将该服务器的消息放在其内部队列上 编辑:处理消息伪代码:
void handle(message)
targetMachine = message.targetMachine
if (targetMachine.thread != null)
targetMachine.thread.addToQueue(message);
else
targetMachine.thread = this;
process(message);
processAllQueueMessages();
targetMachine.thread = null;
处理消息Java代码:(我可能有点过于复杂,但这应该是线程安全的)
每台机器有一个线程ID。生成所需数量的线程。让所有线程贪婪地处理来自全局队列的消息。每个线程都将当前消息的服务器锁定为自己独占使用(直到它处理完当前消息及其队列上的所有消息为止),其他线程将该服务器的消息放在其内部队列上 编辑:处理消息伪代码:
void handle(message)
targetMachine = message.targetMachine
if (targetMachine.thread != null)
targetMachine.thread.addToQueue(message);
else
targetMachine.thread = this;
process(message);
processAllQueueMessages();
targetMachine.thread = null;
处理消息Java代码:(我可能有点过于复杂,但这应该是线程安全的)
退房也许会有帮助,看看吧。也许会有帮助。这是一个非常正确的观点;抱歉,我不清楚,这些状态更改是外部触发的,我想在内部对它们进行排队;很抱歉,我不清楚,这些状态更改是从外部触发的,我想将它们排入队列