2016-01-13 62 views
2

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

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

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

发起一个有序的关闭在以前已提交任务的执行中 ,但没有新的任务将被接受。如果已关闭,则调用没有 附加效果。

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

所以

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