我创建了一个线程池,其中每个线程从队列中获取一个对象并对其进行处理。我不确定我是否以正确的方式实现了它。这是代码:
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处理对象做一些事情。这样正确吗?
谢谢
最佳答案
首先,在构造函数内部创建,提交并关闭ExecutorService
并不是一个好习惯。
看shutdown() javadoc
Initiates an orderly shutdown in which previously submitted tasks are executed, but no new tasks will be accepted. Invocation has no additional effect if already shut down.
您没有发布
IQueueObjectHandler
,但是对我来说,您的ThreadClass作业将无限运行,如果您不通过在objectHandler.handleItem(..)
内显式抛出一些未经检查的异常来停止它们,那将是当然的,这将是错误的。由于这些无限运行的非守护线程,您可能会遇到JVM终止的问题。 (JVM graceful termination conditions)另外,您在执行
InterruptedException
时未捕获queue.take()
,这会导致编译时错误。正确处理InterruptedException
可以帮助您停止可能的shutdownNow()
。所以
shutdownNow()
实际停止执行程序的线程,如果它们处于无限循环中,请为此在InterruptedException
中处理ThreadClass
。或者,您可以使用volatile boolean
或AtomicBoolean
标志(指示状态,正在运行/已停止)将其停止。在需要关闭作业时,请在循环中检查标志并将其更改为false
。 ExecutorService service
设置为实例变量,而不是局部变量。丢失对运行ExecutorService
的引用看起来很糟糕。这可以在其他地方为您提供帮助。 关于java - 使用同一对象的线程池,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34771444/