我创建了一个线程池,每个线程从队列中获取一个对象并处理它。我不确定我是否以正确的方式实施了它。这是代码:
public class HandlerThreadsPool<T> {
private BlockingQueue<T> queue;
private IQueueObjectHandler<T> objectHandler;
private class ThreadClass implements Runnable {
@Override
public void run() {
while (true) {
objectHandler.handleItem(queue.take());
}
}
}
public HandlerThreadsPool(int numberOfThreads, BlockingQueue<T> queue, IQueueObjectHandler<T> dataHandler){
this.queue = queue;
this.objectHandler = dataHandler;
ExecutorService service = Executors.newFixedThreadPool(numberOfThreads);
for (int i = 0; i < numberOfThreads; i++)
service.execute(new ThreadClass());
service.shutdown();
}
}
dataHandler处理对象做一些事情。这样是正确的吗? 感谢
答案 0 :(得分:0)
首先,在构造函数中创建,提交和关闭ExecutorService
不是一个好习惯。
看shutdown() javadoc
启动以前提交的任务的有序关闭 已执行,但不会接受任何新任务。调用没有 如果已经关闭,则会产生额外的影响。
你没有发布IQueueObjectHandler
,但是对我来说,你的ThreadClass作业将无限运行,如果你没有通过在objectHandler.handleItem(..)
内明确地抛出一些未经检查的异常来阻止它们,那么错误。由于这些无限运行的守护程序线程,您可能会遇到JVM终止问题。 (JVM graceful termination conditions)
另外,在执行InterruptedException
时不会捕获queue.take()
,这会导致编译时错误。正确处理InterruptedException
可以帮助您停止shutdownNow()
。
所以
shutdownNow()
实际停止执行程序的线程,如果它们处于无限循环中,则在InterruptedException
内处理ThreadClass
。或者您可以使用volatile boolean
或AtomicBoolean
标志来停止它们,该标志指示状态,运行/停止。检查循环中的标志,并在需要关闭作业时将其更改为false
。ExecutorService service
成为实例变量,而不是本地变量。失去对运行ExecutorService
的引用看起来很糟糕。这可以帮助你在其他地方。