2017-02-14 63 views
1

我有下面的代码片段:ExecutorService(int n)和Thread.activeCount()如何工作?

int k = 4; 

     ExecutorService e = Executors.newFixedThreadPool(k); 
     for (int i = 1; i <= k; i++) { 
      e.execute(new C(i)); 
      e.execute(new C(i)); 
     } 
     int active = Thread.activeCount(); 
     System.out.println(active); 
     e.shutdown(); 

清晰可见我提交两份C每次迭代通过循环。在我的情况下,提交了8 C,即使ExecutorService的固定大小为4. 也可以通过对活动线程数为5进行计数来确认。

此行为是否适用?我不明白为什么看起来只有4个新线程开始计算,尽管8个提交。如果有人能为我清理ExecutorService和Thread.activeCount()的概念,我会非常高兴。

+0

*是此行为意*哪些行为?你觉得什么令人惊讶?你会期待什么样的行为? – shmosel

+0

@shmosel,如果你不熟悉优惠条款,我会参考你的阅读:http://dictionary.cambridge.org/dictionary/english/concessive-clause – blauerschluessel

+1

**在我的情况下,提交8 C,即使ExecutorService具有4 **的固定大小,Executors.newFixedThreadPool(int),处理当前同时运行的4个线程,并且当任何线程完成其执行时,通过e.execute(Runnable)排队的其他4个线程将采用取代死亡线程的位置,否则那些OTHER 4 FROM 8线程将等待OTHER 8 FROM线程完成,这些线程在池中处于运行状态,没有意图让人惊讶,尽管 – ShayHaned

回答

3

您创建的ExecutorService的主要目标是固定大小的线程池(在您的情况下是四个线程)。如果您只看到为您的八件作品创建的四个Thread实例,则它按照设计工作。

你似乎认为应该有8个线程创建。想象一下,如果你提交了一百万件作品,如果创建了一百万个线程,那将是一场灾难。

抽象允许您控制一次使用多少个线程,而不考虑要处理多少个项目。 ExecutorService处理重复使用四个线程的复杂性,根据需要处理所有传递给execute的项目。

一个可能解释这个问题的类比是银行。您创建了一个有四个出纳员(线程池中的四个线程)和八个客户(八个呼叫execute)的银行。当出纳员与客户结束时,排队的下一位客户得到该出纳员的服务。您可以通过致电execute将某人添加到队列中,并由ExecutorService管理其他任何事情。您可以通过初始化ExecutorService(您可以创建许多不同的风格)来控制线程数量(出纳员)。

+0

很好的回答!我从阅读评论中得到了一个猜测,但现在证实了我的猜测。不过,我现在发现其他一些有趣的地方:例如:客户究竟在哪里?在你的比喻中,他们当然是在银行,但是电话在哪里?他们如何存储,他们如何被访问?是否也可以在中途操纵它们,也许为什么其他呼叫到达?你认为我应该打开另一个问题吗? – blauerschluessel

1

我不明白为什么看起来只有4个新的线程开始和计数,尽管8提交。

不要在线程和任务之间混淆。您已为4个线程创建了固定的ThreadPool,并且池中只剩下4个线程。

检查的Executors

/** 
    * Creates a thread pool that reuses a fixed number of threads 
    * operating off a shared unbounded queue. At any point, at most 
    * <tt>nThreads</tt> threads will be active processing tasks. 
    * If additional tasks are submitted when all threads are active, 
    * they will wait in the queue until a thread is available. 
    * If any thread terminates due to a failure during execution 
    * prior to shutdown, a new one will take its place if needed to 
    * execute subsequent tasks. The threads in the pool will exist 
    * until it is explicitly {@link ExecutorService#shutdown shutdown}. 
    * 
    * @param nThreads the number of threads in the pool 
    * @return the newly created thread pool 
    * @throws IllegalArgumentException if <tt>nThreads &lt;= 0</tt> 
    */ 
    public static ExecutorService newFixedThreadPool(int nThreads) { 
     return new ThreadPoolExecutor(nThreads, nThreads, 
             0L, TimeUnit.MILLISECONDS, 
             new LinkedBlockingQueue<Runnable>()); 
    } 

实现您可以找到有关官方文档页面的ThreadPoolExecutor各个参数的更多细节。

在你的情况下,线程数是4,职工任务(正在实施Runnable接口)数量8

他们是如何存储,如何对它们进行访问?是否也可以在中途操纵它们,也许为什么其他呼叫到达?

  1. 任务被提交到任务队列(BlockingQueue
  2. 如果BlockingQueue满(有界队列),拒绝策略会被触发。
  3. 如果BlockingQueue未满,工作任务将等待线程提取它们。

相关SE帖子:

How to properly use Java Executor?

Task getting rejected although threads are available