Executor 读音[ɪɡˈzekjətə(r)]-一个贼可特
Thread 读音[θred]-思略的
- Executors.newFixedThreadPool(5) 一池固定线程 适合长期任务,性能好,执行无序
- Executors.newSingleThreadExecutor() 一池一线程 一个任务一个任务执行,保证顺序性
- Executors.newCachedThreadPool() 一池多线程 适合短期异步任务或者负载很轻的服务,类似会扩容
- 仅了解-Executors.newScheduledThreadPool() 创建固定大小的线程,可以延迟或定时的执行任务。
- 仅了解-java8新出的Executors.newWorkStealingPool(int)
Java中的线程池是通过Executor框架实现的,该框架用到了Executor,Executors[类似于Array与Arrays、Collection与Collections辅助工具类],ExecutorService,ThreadPoolExecutor[线程池底层用这个类]这几个类。
体系结构:
java.util.concurrent.Executor : 负责线程的使用与调度的根接口
|--ExecutorService 子接口: 线程池的主要接口
|--ThreadPoolExecutor 线程池的实现类
|--ScheduledExecutorService 子接口:负责线程的调度
|--ScheduledThreadPoolExecutor :继承 ThreadPoolExecutor, 实现 ScheduledExecutorService *
代码演示
/**
* 线程池三种试用方式
* @Author: 小海
* @Description:
* @Date: Create in 22:28 2020-02-01
*/
public class ExecutorsDemo {
public static void main(String[] args) {
// Executor
// ThreadPoolExecutor;
// 一个线程池创建5个固定线程,适合长期任务,性能好
ExecutorService executorService = Executors.newFixedThreadPool(5);
// 一个线程池创建1个线程,一个任务一个任务执行,保证顺序性
executorService = Executors.newSingleThreadExecutor();
// 一个线程池创建N个线程,适合短期异步任务或者负载很轻的服务
executorService = Executors.newCachedThreadPool();
try {
for (int i = 0; i < 10; i++) {
// 程序执行结果如下:最多只有5个线程同时执行任务
// execute只执行
executorService.execute(()->{
System.out.println(Thread.currentThread().getName() + " 办理业务");
});
// submit带返回值
executorService.submit(new FutureTask<>(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
return null;
}
}));
// 模拟长期任务,让线程执行时间变长
// Thread.sleep(200);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// 关闭线程池
executorService.shutdown();
}
}
}
newFixedThreadPool
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
适用场景:可用于Web服务瞬时削峰,但需注意长时间持续高峰情况造成的队列阻塞。
newSingleThreadExecutor
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
定眼一看,这里多了一层FinalizableDelegatedExecutorService包装。对比可以看出,FixedThreadPool可以向下转型为ThreadPoolExecutor,并对其线程池进行配置,而SingleThreadExecutor被包装后,无法成功向下转型。因此,SingleThreadExecutor被定以后,无法修改,做到了真正的Single。
newCachedThreadPool
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
- corePoolSize = 0,maximumPoolSize = Integer.MAX_VALUE,即线程数量几乎无限制;
- workQueue 为 SynchronousQueue 同步队列,这个队列类似于一个接力棒,入队出队必须同时传递,因为CachedThreadPool线程创建无限制,不会有队列等待,所以使用SynchronousQueue;
- 适用场景:快速处理大量耗时较短的任务,如Netty的NIO接受请求时,可使用CachedThreadPool。