线程池使用相同的对象

时间:2016-01-13 16:06:31

标签: java multithreading queue threadpool threadpoolexecutor

我创建了一个线程池,每个线程从队列中获取一个对象并处理它。我不确定我是否以正确的方式实施了它。这是代码:

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处理对象做一些事情。这样是正确的吗? 感谢

1 个答案:

答案 0 :(得分:0)

首先,在构造函数中创建,提交和关闭ExecutorService不是一个好习惯。 看shutdown() javadoc

  

启动以前提交的任务的有序关闭   已执行,但不会接受任何新任务。调用没有   如果已经关闭,则会产生额外的影响。

你没有发布IQueueObjectHandler,但是对我来说,你的ThreadClass作业将无限运行,如果你没有通过在objectHandler.handleItem(..)内明确地抛出一些未经检查的异常来阻止它们,那么错误。由于这些无限运行的守护程序线程,您可能会遇到JVM终止问题。 (JVM graceful termination conditions
另外,在执行InterruptedException时不会捕获queue.take(),这会导致编译时错误。正确处理InterruptedException可以帮助您停止shutdownNow()

所以

  • 不要在构造函数中关闭池,这会导致问题。如果您不想在其他地方关闭,请使用Runtime.getRuntime().addShutdownHook(..)
  • 使用shutdownNow()实际停止执行程序的线程,如果它们处于无限循环中,则在InterruptedException内处理ThreadClass。或者您可以使用volatile booleanAtomicBoolean标志来停止它们,该标志指示状态,运行/停止。检查循环中的标志,并在需要关闭作业时将其更改为false
  • 使ExecutorService service成为实例变量,而不是本地变量。失去对运行ExecutorService的引用看起来很糟糕。这可以帮助你在其他地方。