线程池使用
// 初始化一个线程池
ExecutorService threadPool = new ThreadPoolExecutor(10, 30, 3, TimeUnit.MINUTES, new LinkedBlockingQueue<>(100));
// 使用
threadPool.submit( () -> { // 执行内容 }
ThreadPoolExecutor
参数
对应参数 (依次)
1、corePoolSize
:核心线程数
核心线程会一直存活,即使没有任务需要执行当线程数小于核心线程数时,即使有线程空闲,线程池也会优先创建新线程处理设置allowCoreThreadTimeout
=true(默认false)时,核心线程会超时关闭
2、maxPoolSize
:最大线程数
当线程数>=corePoolSize
,且任务队列已满时。线程池会创建新线程来处理任务
当线程数=maxPoolSize
,且任务队列已满时,线程池会拒绝处理任务而抛出异常
3、keepAliveTime
:线程空闲时间
当线程数大于核心时,这是多余的空闲线程在终止之前等待新任务的最长时间。
4、unit
时间单位
5、workQueue
:在执行任务之前用于保留任务的队列
LinkedBlockingQueue
链表 这个队列接收到任务的时候,如果当前线程数小于核心线程数,则新建线程(核心线程)处理任务;如果当前线程数等于核心线程数,则进入队列等待。超过(最大线程数+队列长度)报错。
new LinkedBlockingQueue<>(20) // 不填参数默认为无限大 Integer.MAX_VALUE
ArrayBlockingQueue
动态数组 有界 takeIndex
和putIndex
表示存和取的两个数组下标。
这个队列接收到任务的时候,如果当前线程数小于核心线程数,则新建线程(核心线程)处理任务;如果当前线程数等于核心线程数,则进入队列等待。超过(最大线程数+队列长度)报错。
SynchronousQueue
没有容器
/*
默认为 flase
true -> new TransferQueue<E>() :
false -> new TransferStack<E>()
*/
new SynchronousQueue<>(false)
DelayQueue
队列内元素必须实现Delayed接口,这就意味着你传进去的任务必须先实现Delayed接口。这个队列接收到任务时,首先先入队,只有达到了指定的延时时间,才会执行任务
CountDownLatch
使用
线程是异步执行的如果需要返回结果,则需要使用 CountDownLatch
// 线程开始执行前 初始计数
CountDownLatch countDownLatch = new CountDownLatch(20);
// 线程执行中 每执行一次 进行减一
countDownLatch.countDown();
// 执行后 等待固定时间后返回结果,无论是否执行完成
boolean await = countDownLatch.await(5, TimeUnit.SECONDS);
if (!await) {
System.out.println("超时");
}
ThreadPoolExecutor
执行顺序
线程池按以下行为执行任务
- 当线程数小于核心线程数时,创建线程。
- 当线程数大于等于核心线程数,且任务队列未满时,将任务放入任务队列。
- 当线程数大于等于核心线程数,且任务队列已满
- 若线程数小于最大线程数,创建线程
- 若线程数等于最大线程数,抛出异常,拒绝任务
线程池的状态
running
状态:当线程池创建后,初始为running
状态shutdown
状态:调用shutdown
方法后,处在shutdown
状态,此时不再接受新的任务,等待已有的任务执行完毕stop
状态:调用shutdownnow
方法后,进入 stop 状态,不再接受新的任务,并且会尝试终止正在执行的任务。terminated
状态:当处于shotdown
或 stop 状态,并且所有工作线程已经销毁,任务缓存队列已清空,线程池被设为terminated
状态。
常用线程池
ScheduledThreadPoolExecutor
延时线程池
ScheduledThreadPoolExecutor scheduled = new ScheduledThreadPoolExecutor(5);
// 指定核心线程数
scheduled.schedule(() -> { 执行语句; }, 5, TimeUnit.SECONDS);
//达到给定的延时时间后,执行任务。这里传入的是实现Runnable接口的任务,
//因此通过ScheduledFuture.get()获取结果为null
public ScheduledFuture<?> schedule(Runnable command,
long delay, TimeUnit unit);
//达到给定的延时时间后,执行任务。这里传入的是实现Callable接口的任务,
//因此,返回的是任务的最终计算结果
public <V> ScheduledFuture<V> schedule(Callable<V> callable,
long delay, TimeUnit unit);
//是以上一个任务开始的时间计时,period时间过去后,a
//检测上一个任务是否执行完毕,如果上一个任务执行完毕,
//则当前任务立即执行,如果上一个任务没有执行完毕,则需要等上一个任务执行完毕后立即执行
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
long initialDelay,
long period,
TimeUnit unit);
//当达到延时时间initialDelay后,任务开始执行。上一个任务执行结束后到下一次
//任务执行,中间延时时间间隔为delay。以这种方式,周期性执行任务。
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,
long initialDelay,
long delay,
TimeUnit unit);
newCachedThreadPool
缓存线程池
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
newSingleThreadExecutor
单线程的线程池
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
newFixedThreadPool
定长线程池
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}