2017-04-23 54 views
2

我很困惑,当新的线程为执行创造了约。我的理解是:对于cachedthreadpool,根据提交的任务创建新线程。至于fixedthreadpool和singlethread,无论提交什么任务,都会预先创建线程。我的理解错了吗?什么时候执行真正创造新的线程

ExecutorService exec = Executors.newCachedThreadPool(); 
exec.execute(new LiftOff()); 

ExecutorService exec = Executors.newFixedThreadPool(3); // Are the three threads created 
                 // after this line executes? 
exec.execute(new LiftOff()); 

ExecutorService exec = Executors.newSingleThreadExecutor(); // Is the single thread created 
                  // after this line executes? 
exec.execute(new LiftOff()); 
+4

你能回答使用调试器这些问题,或者通过查看代码为'执行者'。 –

+0

这些方法中的每一个都有一个接受'ThreadFactory'的变体,您可以传入自己的实现,该实现在线程被请求时进行记录。 – pvg

回答

1

简短的回答是,在所有的情况下,你所提到的,只有当你开始执行任务线程创建的,即执行该ExecutorService exec = Executors.newFixedThreadPool(3);行后没有线程将被创建,并第一个线程将只创建在此之后exec.execute(new LiftOff());行被执行。


为了更好地和充分理解这一点,因为@Oliver已告知您需要通过Java源代码走路,也了解ThreadPoolExecutor,尤其是什么核心池大小,最大池大小等,如果要快速理解这个在外行的话,然后阅读this good answer

现在,下面是几个好点,了解我带你们去一些示例代码之前:

  • Java的实用工具类Executors将创建并返回ExecutorService对象(请注意:ExecutorService是一个接口)。
  • 现在如果是newCachedThreadPool(),newFixedThreadPool(int nThreads),您将得到ThreadPoolExecutor(请注意,ThreadPoolExecutor实现ExecutorService接口)的对象。
  • 正如您在源代码中看到的那样,当您执行Executors.newFixedThreadPool(3);时,您只会得到一个对象ThreadPoolExecutor,其中包含所有实例变量,例如核心池大小,最大池大小等设置,在您的情况下它将设置为3
  • 此时没有创建线程,并且实际创建线程仅在使用execute,submitinvokeAll开始执行任务时发生。
  • 正如你可以在源代码中看到的,当你做第一execute如果当前的池大小小于核心池大小也只能建立1个新的线程,所以这是你的线程开始得到创造。

请参阅下面的示例代码,它将帮助您了解并证明线程仅在开始执行任务时创建。 为了解释你,我做的主要技巧是我使用了对象引用变量ThreadPoolExecutor,这样我就可以调用方法,如getPoolSize()(请注意,getPoolSize()讲述了当前存在于池中的线程数),因为当您使用对象的ExecutorService引用变量,那么你不能调用这些方法(我相信我不需要告诉“为什么”)。

当你运行这个例子,你会注意到,

  • 目前还没有ThreadPoolExecutor poolExecutor = (ThreadPoolExecutor) Executors.newFixedThreadPool(3);
  • 后创建的你有在池中的一个线程首先executeRunnable(poolExecutor);后线程。
  • 既然你已经使用的核心池大小为3,所以创建3个线程之后创建没有更多的线程。(请阅读核心,最大池大小和“队列”大小)

package com.learn.stackoverflow.multithreading; 

import java.util.Date; 
import java.util.concurrent.Executors; 
import java.util.concurrent.ThreadPoolExecutor; 

/** 
* 
* @author himanshu.agrawal 
* 
*/ 
public class ExecutorServiceNumberOfThreads { 
    public static void main(String[] args) { 
     System.out.println("### Testing Executors.newFixedThreadPool()"); 
     testNewFixedThreadPool(); 
    } 

    private static void testNewFixedThreadPool() { 
     ThreadPoolExecutor poolExecutor = (ThreadPoolExecutor) Executors.newFixedThreadPool(3); 
     System.out.println("Pool when no execute() : " + poolExecutor.getPoolSize()); 
     executeRunnable(poolExecutor); 
     System.out.println("Pool after 1st execute() : " + poolExecutor.getPoolSize()); 
     executeRunnable(poolExecutor); 
     System.out.println("Pool after 2nd execute() : " + poolExecutor.getPoolSize()); 
     executeRunnable(poolExecutor); 
     System.out.println("Pool after 3rd execute() : " + poolExecutor.getPoolSize()); 
     executeRunnable(poolExecutor); 
     System.out.println("Pool after 4th execute() : " + poolExecutor.getPoolSize()); 
     executeRunnable(poolExecutor); 
     System.out.println("Pool after 5th execute() : " + poolExecutor.getPoolSize()); 
    } 

    private static void executeRunnable(ThreadPoolExecutor poolExecutor) { 
     poolExecutor.execute(new Runnable() { 

      @Override 
      public void run() { 
       System.out.println("Running: " + Thread.currentThread().getId() + " | " + new Date()); 
      } 
     }); 
    } 

} 

输出:

### Testing Executors.newFixedThreadPool() 
Pool when no execute() : 0 
Pool after 1st execute() : 1 
Pool after 2nd execute() : 2 
Pool after 3rd execute() : 3 
Pool after 4th execute() : 3 
Pool after 5th execute() : 3 
Running: 10 | Sun Apr 23 19:50:32 IST 2017 
Running: 8 | Sun Apr 23 19:50:32 IST 2017 
Running: 10 | Sun Apr 23 19:50:32 IST 2017 
Running: 9 | Sun Apr 23 19:50:32 IST 2017 
Running: 8 | Sun Apr 23 19:50:32 IST 2017 
+1

非常清楚。我通常阅读Java文档,但我认为阅读源代码对我来说很困难。 – user7328234

+0

谢谢,没问题。许多专家表示,检查并试图理解源代码是理解Java中某些东西的最佳方式。 – hagrawal