简短的回答是,在所有的情况下,你所提到的,只有当你开始执行任务线程创建的,即执行该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
,submit
或invokeAll
开始执行任务时发生。
- 正如你可以在源代码中看到的,当你做第一
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
你能回答使用调试器这些问题,或者通过查看代码为'执行者'。 –
这些方法中的每一个都有一个接受'ThreadFactory'的变体,您可以传入自己的实现,该实现在线程被请求时进行记录。 – pvg