[英]What design pattern to use for a threaded queue
我有一个非常复杂的系统(100多个线程)需要发送电子邮件而不会阻塞。 我解决这个问题的方法是实现一个名为EmailQueueSender
的类,该类在执行开始时启动,并有一个ScheduledExecutorService
,它每隔500ms查看一个内部队列,如果size()> 0则清空它。
虽然这是一个名为addEmailToQueue(String[])
的同步静态方法,它接受一个包含body,subject..etc作为数组的电子邮件。 系统确实有效,我的其他线程可以继续将他们的电子邮件添加到队列中而不会阻塞,甚至担心电子邮件是否成功发送...它似乎有点乱......或者说是hackish ...每个程序员当他们知道自己做错了什么或者有更好的方法时,会在胃里感受到这种感觉。 也就是说,有人可以打我的手腕,并提出一个更有效的方法来实现这一目标吗?
谢谢!
http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/ThreadPoolExecutor.html
仅此课程可能会处理您需要的大部分内容。 只需将发送代码放在runnable中,然后使用execute方法添加它。 getQueue方法将允许您检索当前的等待项列表,以便您可以在重新启动发送方服务时保存它而不会丢失电子邮件
如果您使用的是Java 6,则可以大量使用java.util.concurrent
包中的原语。
拥有一个处理实际发送的单独线程是完全正常的。 我宁愿使用BlockingQueue
而不是轮询队列,因为你可以使用阻塞take()
而不是busy-waiting。
如果您对电子邮件是否成功发送感兴趣,您的append方法可以返回Future
以便您可以在发送邮件后传递返回值。
我建议创建一个(几乎无关紧要的)Java类来保存值,而不是使用字符串数组。 如今,对象创建很便宜。
我不确定这是否适用于您的应用程序,但听起来就像它会。 ThreadPoolExecutor
( ExecutorService
-implementation)可以将BlockingQueue
作为参数,您只需将新线程添加到队列中即可。 完成后,您只需终止ThreadPoolExecutor
。
private BlockingQueue<Runnable> queue;
...
ThreadPoolExecutor executor = new ThreadPoolExecutor(10, 10, new Long(1000),
TimeUnit.MILLISECONDS, this.queue);
您可以保留添加到队列中的所有线程的计数。 当你认为你已经完成时(队列是空的,或许?)只需将其与之比较即可
if (issuedThreads == pool.getCompletedTaskCount()) {
pool.shutdown();
}
如果两者匹配,你就完成了。 终止池的另一种方法是在循环中等待一秒:
try {
while (!this.pool.awaitTermination(1000, TimeUnit.MILLISECONDS));
} catch (InterruptedException e) {//log exception...}
有许多软件包和工具可以帮助解决这个问题,但是在计算机科学中广泛研究的这类案例的通用名称是生产者 - 消费者问题 。 有各种众所周知的解决方案,可以被认为是“设计模式”。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.