2014-03-01 40 views
5

,我读了ThreadPoolExecutor拥有的线程池,该池是注定要降低创造新线程的成本(至少我理解这样的方式如下短语):的ThreadPoolExecutor:它是怎样重用线程

当你发送任务给执行程序,它会尝试使用池线程 来执行此任务,以避免连续产生 线程。 [Java 7的并发菜谱]

,因为我知道我们有没有办法重新启动线程Java编写的。

问题: ThreadPoolExecutor如何避免创建新线程?

回答

9

这非常简单 - 实质上是Thread的睡眠,等待被任务唤醒 - 他们运行该任务,然后再次入睡。

public static void main(final String[] args) throws Exception { 
    final BlockingQueue<Runnable> blockingQueue = new LinkedBlockingDeque<>(); 
    final Thread t = new Thread(new Runnable() { 

     @Override 
     public void run() { 
      while (true) { 
       try { 
        blockingQueue.take().run(); 
       } catch (InterruptedException ex) { 
        return; 
       } 
      } 
     } 
    }); 
    t.start(); 
    blockingQueue.add(new Runnable() { 

     @Override 
     public void run() { 
      System.out.println("Task 1"); 
     } 
    }); 
    blockingQueue.add(new Runnable() { 

     @Override 
     public void run() { 
      System.out.println("Task 2"); 
     } 
    }); 
} 

BlockingQueue将阻止一个Thread而它是空的。当我添加一个项目时,当前被阻止的Thread(s)被唤醒,并且一个将执行任务(LinkedBlockingDeque是线程安全的)。当Thread完成任务后,它会重新进入睡眠状态。

JavaDoc对于ThreadPoolExecutor描述了详细的逻辑。 ThreadPoolExecutor的所有构造函数都采用BlockingQueue<Runnable> - 这应该给您提示逻辑如何工作的提示。

注意:这不等于忙等待。 A BlockingQueue使用waitnotify暂停和唤醒Thread s,这意味着池中的Thread在未处理任务时没有做任何工作。由于Thread会阻止所有CPU核心的轮询,从而不允许程序继续进行(或者至少严重损害它),所以基于等待的忙碌方法将不起作用

+0

鲍里斯的好信息。另外,它们将每个调用都包含在try-catch可抛出对象的worker run方法中,以便线程永远不会被调用,而不管被调用的方法中发生了什么错误。或者其他方式来跟踪活动线程并在需要时创建一个新线程? – tgkprog

+0

@tgkprog确实是 - 提交的代码被封装在一个自定义的'Runnable'中,该定制不仅处理'Exception'处理,而且还处理通过'Callable - > Future 'API执行的返回值。如果你想要实现的细节,最好只看[源代码](http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/concurrent /ThreadPoolExecutor.java)。 –

相关问题