ThreadPoolExecutor的线程池浅析
1. 线程池的介绍
线程池就是先创建一些线程,把创建的这些线程都放入一个池子(集合)中称为线程池。线程池可以很好的提高性能,当有一个新的任务传给线程池,线程池就会启动一个线程来执行这个任务,执行结束后该线程会返回线程池中进入空闲状态并不会死亡,等待下一个任务的到来。
比如你在滴滴打车的时候,附近的每一辆车就是线程池中的每一个线程,要打车的用户就是线程池要执行的任务, 比如附近只有五辆车(线程池最大为5)但是现在有15个用户在打车,所以只能有5个用户先出发(线程运行最大数量),剩下的用户都需要等待前面的用户打完车 (等待的队列)。
2. 线程池的工作流程
-
线程池判断核心线程池里的线程是否都执行任务。如果不是,则创建一个新的工作线程来执行任务。如果核心线程池里的线程都在执行任务,进入下个流程。
-
线程池判断工作队列是否已经满。如果工作队列没有满,则将新提交的任务存储在这个工作队列中。如果工作队列满了,进入下个流程。
-
线程池判断线程池的最大线程是否都处于工作状态。如果没有,创建一个新的工作线程来执行任务。如果满了,交给拒绝策略来处理这个任务
3. 创建线程池
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
-
corePoolSize 核心线程数量 (不会被回收)可以设置allowCoreThreadTimeout 这个参数为true,核心线程也会被回收。(默认是false
-
maximumPoolSize 最大线程数量 当核心线程到达最大值,并且队列中也到最大值,就会创建新的线程
-
keepAliveTime 设置非核心线程最多保持多长时间默认 0 (超过这个时间会去回收不是核心的线程 回收的数量也就是 maximumPoolSize - corePoolSize
-
TimeUnit (keepAliveTime 的单位
-
workQueue 创建队列的方式 (当新的任务来临后并且核心线程满了之后会创建队列来进行排队等待
-
threadFactory 表示线程的创建工厂,此参数一般用的比较少,我们通常在创建线程池时不指定此参数,它会使用默认的线程创建工厂的方法来创建线程,
-
handler 拒绝策略 当队列达到最大值并且 最大线程池( maximumPoolSize)也是最大值,这时新来的任务没有地方储存,则会使用拒绝策略
4. ThreadPoolExecutor的执行方式
ThreadPoolExecutor 的执行方法有两种,分别为:execute() 和 submit() 。
public static ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5, 5, 20,
TimeUnit.SECONDS, new LinkedBlockingQueue<>(), new ThreadPoolExecutor.CallerRunsPolicy());
public static void main(String[] args) throws ExecutionException, InterruptedException {
threadPoolExecutor.execute(() -> System.out.println("Hello execute"));
Future<String> submit = threadPoolExecutor.submit(() -> "我是submit启动的");
System.out.println(submit.get());
}
5. submit和execute方法的区别
-
submit() 方法可以接收线程池执行的返回值,而 execute() 不能接收返回值。
-
它们还有一个区别是 execute() 方法属于 Executor 接口的方法,而 submit() 方法则是属于
ExecutorService 接口的方法