面试系列 - java线程池
线程池在日常开发中还是很常见的。比如要刷数据或者日常开发中有大量数据要处理的时候,为了提高响应时间就需要开多线程来实现。
Executors 快速创建线程池
java中可以通过 Executors快速创建线程池,具体的用法有三种(Executors.newXXX):
方法 | 特点 |
---|---|
newFixedThreadPool(int nThreads) | 指定线程数的线程池 |
newSingleThreadExecutor() | 单个线程的线程池 |
newCachedThreadPool() | 不限线程数的线程池 |
具体的源码如下:
/*指定线程数的线程池*/
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
/*单个线程的线程池*/
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
/*不限线程数的线程池*/
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
我们可以看到快速创建线程池的底层还是使用的ThreadPoolExecutor这个方法。只是针对不同的方法做了不同的参数设置,如果在不关心其他参数(超时时间、等待队列、拒绝策略)设置的情况下,可以使用快速方法创建线程池。
ThreadPoolExecutor 构造器
参数介绍
public ThreadPoolExecutor(int corePoolSize, //核心线程数量 默认即使处于空闲状态(不会回收 可以通过参数设置allowCoreThreadTimeOut)
int maximumPoolSize, //最大线程数
long keepAliveTime, //超过corePoolSize 线程的存活时间
TimeUnit unit,//keepAliveTime的单位
BlockingQueue<Runnable> workQueue, //任务队列(保存已经提交但是还没有执行完毕的线程),当核心线程不空闲时,任务将会被添加到任务队列(execute之后没有线程执行)
ThreadFactory threadFactory,//创建线程的工厂
RejectedExecutionHandler handler) //线程数量 = maximumPoolSize & workQueue 满了 新的线程请求拒绝策略
/*
* 新线程请求到来时 corePoolSize > workQueue > maximumPoolSize
* 当corePoolSize 不满时就创建新的线程(核心)
* 当corePoolSize满时 & 队列未满 创建新的线程 往队列里添加
* 当corePoolSize满时 & 队列满 & 总线程数 < maximumPoolSize 创建新线程(普通线程,超时会被回收)
* 当corePoolSize满时 & 队列满 & 总线程数 = maximumPoolSize handler处理(拒绝策略)
*/
拒绝策略
拒绝策略 | 拒绝方法 |
---|---|
AbortPolicy | 抛出异常 RejectedExecutionException |
DiscardPolicy | 什么也不做,直接忽略 |
DiscardOldestPolicy | 丢弃执行队列中最老的任务,尝试为当前提交的任务腾出位置 |
CallerRunsPolicy | 直接由提交任务者执行这个任务 |
Runnable & Callable
区别:Callable是jdk1.5对Runnable的一种补充,可以返回线程的执行结果可以抛异常
1、方法签名不同
void Runnable.run(),
V Callable.call() throws Exception
2、Callable允许有返回值
3、Callable允许抛出异常
//不返回结果
void execute(Runnable command);
//future.get()可以获取执行结果
<T> Future<T> submit(Callable<T> task);
//future.get()返回入参result
<T> Future<T> submit(Runnable task, T result);
//future.get()返回null
Future<?> submit(Runnable task);
//forEach(List<Future<T>>) {future.get()}可以获取执行结果 0<i<thirdSize是线程的index
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
throws InterruptedException;
关闭线程池
/*正在执行的线程、已在等待队列里的任务会继续执行下去,不再接受新任务 ,异步中断闲置的的线程*/
void shutdown();
/*尝试停止所有正在执行的任务,停止处理等待的任务,并返回等待执行的任务列表*/
List<Runnable> shutdownNow();
/* 返回是否已经关闭 */
boolean isShutdown();
/*所有的线程是否都已经执行完毕等待关闭*/
boolean isTerminated();
/*阻塞,直到所有任务在关闭请求后完成执行(发生超时/当前线程中断)*/
boolean awaitTermination(long timeout, TimeUnit unit)
throws InterruptedException;