前言
池化技术已经屡见不鲜了,比如数据库连接池,大家的项目中应该也用到了线程池。池化技术的好处:降低资源的消耗,提高响应速度,提高线程的可管理性。本篇主要是和大家一起分析下线程池的架构和它的工作流程。
1、线程池架构图
架构图中,有三个接口,三个类,下面分别介绍下它们:
1、Executor
public interface Executor {
void execute(Runnable command);
}
Executor的接口只定义了一个方法,该方法是用来执行已提交的 Runnable 任务的对象。
2、ExecutorService
ExecutorService定义了一系列的“提交”、“关闭”、“执行”等方法,来服务于Executor,从命名上咱们也能理解为什么叫ExecutorService。
3、AbstractExecutorService
AbstractExecutorService抽象类为ExecutorService中的函数接口提供了默认实现。
4、ThreadPoolExecutor
ThreadPoolExecutor这个就是我们常说的“线程池”,该类继承了AbstractExecutorService,具体的分析会在下一篇重点分析。
5、ScheduledExecutorService
ScheduledExecutorService接口从名字上就可以看出来,它相当于提供了“延迟”、“周期”功能的ExecutorService。
6、ScheduledThreadPoolExecutor
ScheduledThreadPoolExecutor类就是提供了“延迟”、“周期”功能的ThreadPoolExecutor。
2、工作流程
- 主线程创建实现Runnable或Callable接口的任务对象。
- 主线程将任务对象交给ExecutorService的实现类(ThreadPoolExecutor或ScheduledThreadPoolExecutor对象)执行execut或者submit方法来执行。
- ExecutorService若执行execut方法,则不返回结果;若执行submit方法,则返回FutureTask对象。
- 若有返回对象,主线程则执行 FutureTask.get()方法等待任务执行完成。
3、示例
public class ThreadPoolTest {
//这里是创建一个2个固定线程的线程池
//《阿里巴巴 Java 开发手册》中强制不允许使用 Executors 去创建线程池
//详细解释会在下一篇后面给出
private static ExecutorService executorService = Executors.newFixedThreadPool(2);
public static void main(String[] args) {
for (int i=0; i<10; i++){
//创建实现Runnable接口的对象
Runnable thread = new MyRunnable();
//执行任务
executorService.execute(thread);
}
executorService.shutdown();
}
}
class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}
控制台输出:
pool-1-thread-1
pool-1-thread-1
pool-1-thread-1
pool-1-thread-1
pool-1-thread-1
pool-1-thread-1
pool-1-thread-1
pool-1-thread-1
pool-1-thread-1
pool-1-thread-2