🌀 技术人生
凡事有交代,件件有着落,事事有回音
面试题:你分析过线程池源码吗?

1.为什么要用线程池?

降低系统资源消耗

提高线程可控性

2.如何创建线程池?

JDK8中提供了5种创建线程池的方法

(1). newFixThreadPool

创建固定大小的线程池,可控制线程最大并发数,超过的线程会在队列中等待 public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue()); }

(2).(JDK8新增) newWorkStealingPool

会根据所需的并发数来动态创建和关闭线程,能够合理的使用CPU进行对任务进行并发操作,所以很适合使用在很耗时的任务上 public static ExecutorService newWorkStealingPool(int parallelism) { return new ForkJoinPool (parallelism, ForkJoinPool.defaultForkJoinWorkerThreadFactory, null, true); }

这里返回的是一个ForkJoinPool对象

public ForkJoinPool(int parallelism, ForkJoinWorkerThreadFactory factory, UncaughtExceptionHandler handler, boolean asyncMode) { this(checkParallelism(parallelism), checkFactory(factory), handler, asyncMode ? FIFO_QUEUE : LIFO_QUEUE, “ForkJoinPool-” + nextPoolId() + “-worker-”); checkPermission(); }

使用一个无限队列来保存需要执行的任务,可以传入线程的数量,不传入的话,默认使用当前计算机中可以使用的CPU数量,使用分治法来解决问题,使用fork()和join()来进行调用

(3).newCashedThreadPool

创建一个可缓存的线程池,可以灵活回收空闲线程,如果无法回收,则新建线程 public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue()); }

(4).newSingleThreadPoolExecutor

创建一个单线程的线程池 public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue())); }

(5).newScheduledThreadPool

创建一个定长线程池,支持定时以及周期性任务执行 public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) { return new ScheduledThreadPoolExecutor(corePoolSize); }

3.源码结构(Executor框架结构)

从上往下依次是:

Executor

一个运行新任务的简单接口

ExecutorService

扩展了Executor接口,添加了一些用来管理执行器生命周期和任务生命周期的方法

AbstractExecutorService

对ExecutorService接口的抽象类实现

ThreadPoolExecutor

Java线程池的核心实现

4.线程池状态的转换模型

running:

线程池一旦被创建,就处于running状态,能够接收新任务,以及对已添加的任务进行处理

shutdown:

不能接收新任务,但能够处理已添加的任务

stop:

不接受新任务,不处理已添加的任务,并且会中断正在处理的任务

tidying:

当所有的任务已经终止,线程池就会变成tidying状态

terminated:

线程池彻底终止,就会变成terminated状态


最后修改于 2020-04-15

知识共享许可协议
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。