【问题标题】:Thread pool using same object使用相同对象的线程池
【发布时间】:2016-04-18 16:59:32
【问题描述】:

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

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 处理对象做一些事情。以这种方式正确吗? 谢谢

【问题讨论】:

    标签: java multithreading queue threadpool threadpoolexecutor


    【解决方案1】:

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

    启动有序关闭,其中先前提交的任务被 执行,但不会接受新任务。调用没有 如果已经关闭,则附加效果。

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

    所以

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-24
      • 2012-10-29
      • 1970-01-01
      • 2019-01-20
      • 1970-01-01
      相关资源
      最近更新 更多