ExecutorService详解(定义作用及6种线程池实现)

ExecutorService详解(定义作用及6种线程池实现)-mikechen

ExecutorService在线程池经常被使用到,下面我就来详解ExecutorService的作用与6种实现@mikechen

什么是ExecutorService

ExecutorService 是 Java 中的一个接口,属于 java.util.concurrent 包,用于管理和控制线程执行的框架。

ExecutorService 提供了一种高级的方法来管理线程池,简化了多线程编程,同时提高了资源利用率。

 

ExecutorService的作用

ExecutorService 接口的主要目的是为了解决直接操作线程带来的一些问题,比如手动管理线程的生命周期、创建和销毁线程的开销,以及线程间通信等问题。

它在多线程环境中有许多重要作用:

  1. 线程池管理: ExecutorService 封装了线程池的概念,它通过管理一组预创建的线程,可以有效地重用线程,从而降低了线程创建和销毁的开销。
  2. 任务调度: ExecutorService 允许你提交任务,然后自动调度线程来执行这些任务,你不必手动创建和启动线程,从而减少了因线程管理而引入的错误。
  3. 异步执行: 提交任务给 ExecutorService 后,它会异步地执行任务,使得你的程序可以继续执行其他操作,而不需要等待任务完成。
  4. 异常处理: ExecutorService 可以捕获和处理任务执行过程中可能抛出的异常,从而更好地控制和处理错误情况。

 

ExecutorService的实现

1.ThreadPoolExecutor

ThreadPoolExecutor 是一个灵活的线程池实现,允许你自定义线程池的各种参数。

如下所示:

ThreadPoolExecutor executor = new ThreadPoolExecutor(
    2, // corePoolSize
    5, // maximumPoolSize
    60, TimeUnit.SECONDS, // keepAliveTime
    new LinkedBlockingQueue<Runnable>() // workQueue
);

executor.submit(() -> System.out.println("Task executed."));
executor.shutdown();

上就自定义了:核心线程数、最大线程数、线程空闲时间等。

 

2.ScheduledThreadPoolExecutor

ScheduledThreadPoolExecutor 是支持计划执行任务的线程池,可以延迟任务执行或者周期性地执行任务。

如下所示:

ScheduledExecutorService executor = Executors.newScheduledThreadPool(2);

executor.schedule(() -> System.out.println("Scheduled task"), 5, TimeUnit.SECONDS);
executor.scheduleAtFixedRate(() -> System.out.println("Recurring task"), 0, 2, TimeUnit.SECONDS);

它允许你安排任务在未来的某个时间点执行,或者以固定时间间隔重复执行。

 

3.FixedThreadPool

FixedThreadPool 是一个具有固定大小的线程池,适用于需要限制并发线程数的情况。

如下所示:

ExecutorService executor = Executors.newFixedThreadPool(3);

for (int i = 0; i < 10; i++) {
    final int taskNumber = i;
    executor.submit(() -> System.out.println("Task " + taskNumber + " executed."));
}

executor.shutdown();

上面创建了一个具有固定线程数的线程池,一旦线程被创建,它们会一直存在,直到线程池被关闭。

 

4.CachedThreadPool

Executors.newCachedThreadPool() 方法返回一个根据需求自动调整大小的线程池。

如下所示:

ExecutorService executor = Executors.newCachedThreadPool();

for (int i = 0; i < 10; i++) {
    final int taskNumber = i;
    executor.submit(() -> System.out.println("Task " + taskNumber + " executed."));
}

executor.shutdown();

线程池会根据任务的数量自动创建新线程,当线程空闲一段时间后,它们会被回收。

 

5.SingleThreadExecutor

Executors.newSingleThreadExecutor() 方法返回一个只有一个线程的线程池,用于顺序执行任务。

如下所示:

ExecutorService executor = Executors.newSingleThreadExecutor();

for (int i = 0; i < 5; i++) {
    final int taskNumber = i;
    executor.submit(() -> System.out.println("Task " + taskNumber + " executed."));
}

executor.shutdown();

适用于需要确保任务按顺序执行的场景。

 

6.WorkStealingPool

Executors.newWorkStealingPool() 方法返回一个基于工作窃取算法的线程池。

如下所示:

ExecutorService executor = Executors.newSingleThreadExecutor();

for (int i = 0; i < 5; i++) {
    final int taskNumber = i;
    executor.submit(() -> System.out.println("Task " + taskNumber + " executed."));
}

executor.shutdown();

WorkStealingPool 是基于工作窃取算法的线程池,不同线程维护自己的任务队列,可以从其他线程的队列中窃取任务来执行。

陈睿mikechen

十余年BAT架构经验,资深技术专家,就职于阿里、淘宝、百度等一线互联网大厂。

关注「mikechen」公众号,获取更多技术干货!

后台回复面试即可获取《史上最全阿里Java面试题总结》,后台回复架构,即可获取《阿里架构师进阶专题全部合集

评论交流
    说说你的看法