我对创建新线程和执行程序时感到困惑。我的理解是:对于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());
答案 0 :(得分:2)
简短的回答是,在您提到的所有情况下,只有在您开始执行任务时才会创建线程,即在执行此ExecutorService exec = Executors.newFixedThreadPool(3);
行之后不会创建任何线程,并且只有在执行exec.execute(new LiftOff());
行后才会创建线程。
为了更好地理解这一点,正如@Oliver建议你需要浏览Java源代码并阅读ThreadPoolExecutor,特别是核心池大小,最大池大小等等。如果你想快速用外行的话理解这一点,然后阅读this good answer。
现在,在我向您介绍一些示例代码之前,以下几点是很难理解的:
Executors
将创建并返回ExecutorService
的对象(请注意ExecutorService
是一个接口)。 newCachedThreadPool()
,newFixedThreadPool(int nThreads)
,您将获得ThreadPoolExecutor
的对象(请注意ThreadPoolExecutor
实现ExecutorService
接口。)Executors.newFixedThreadPool(3);
时,您只获得ThreadPoolExecutor
的对象,其中包含所有实例变量,如核心池大小,最大池大小等设置,以及你的情况将被设置为3。execute
,submit
或invokeAll
开始执行任务时才会创建实际线程。execute
时,如果当前池大小小于核心池大小,它将只创建一个新线程,因此这是您的线程开始创建的位置。请参阅下面的示例代码,它将帮助您了解并证明只有在您开始执行任务时才创建线程。 为了解释你,我做的主要技巧是使用了ThreadPoolExecutor
的对象引用变量,以便我可以调用类似getPoolSize()
的方法(请注意getPoolSize()
告诉我关于池中当前存在多少个线程),因为当你使用ExecutorService
的对象引用变量时,你不能调用这些方法(我确信我不需要告诉“为什么”)。
当您运行此示例时,您会注意到:
ThreadPoolExecutor poolExecutor = (ThreadPoolExecutor) Executors.newFixedThreadPool(3);
executeRunnable(poolExecutor);
之后,您在池中有一个帖子。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