程序运行,其本质上,是对系统资源(CPU、内存、磁盘、网络等等)的使用。如何高效的使用这些资源是咱们编程优化演进的一个方向。今天说的线程池是对CPU的利用的优化手段。java
网上有很多介绍如何使用线程池的文章,那我想说点什么呢?我但愿查看线程池原理,明白池化技术的基本设计思路。遇到其余类似问题能够解决。编程
何为池化技术,简单点来讲,就是提早保存大量的资源,以备不时之需。在资源有限的状况下,该技术能够大大提高资源的利用率,提高性能等。微信
目前比较典型的池化技术有: 线程池、链接池、内存池、对象池等。网络
本文主要来介绍一下其中比较简单的线程池的实现原理,但愿读者们能够触类旁通,经过对线程池的理解,学习并掌握全部的编程中池化技术的底层原理,一通百通。并发
在java的并发编程中,线程是十分重要的,在Java中,建立一个线程比较简单:ide
public class App {
public static void main(String[] args) throws Exception {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("线程运行中");
}
}).start();
}
}
复制代码
咱们经过建立一个线程对象,而且实现Runnable接口就能够实现一个简单的线程。能够利用上多核CPU。当一个任务结束,当前线程就结束。函数
但不少时候,咱们不止会执行一个任务。若是每次都是如此的建立线程->执行任务->销毁线程,会形成很大的性能开销的。工具
那可否一个线程建立后,执行完一个任务后,又去执行另外一个任务,而不是销毁。这就是线程池。性能
这就是池化技术的思想,经过预先建立好多个线程,放在池中,这样能够在须要使用线程的时候直接获取,避免屡次重复建立、销毁代理的开销。学习
如下代码,就是在java中建立线程池:
import java.util.concurrent.*;
public class App {
public static void main(String[] args) throws Exception {
ExecutorService executorService = new ThreadPoolExecutor(1, 1,
60L, TimeUnit.SECONDS,
new ArrayBlockingQueue<>(10));
executorService.execute(new Runnable() {
@Override
public void run() {
System.out.println("abcdefg");
}
});
executorService.shutdown();
}
}
复制代码
JDK提供给外部的接口也很简单。直接调用ThreadPoolExecutor构造一个就能够了,也能够经过Executors静态工厂构建,但通常不建议。
能够看到,开发者想要在代码中使用线程池仍是比较简单的,这得益于Java给咱们封装好了一系列的API。不少时候,咱们须要知道这些API后面干了些啥,以便于咱们更好的设计与实现咱们的代码。
一般,通常构造函数会反映出这个工具或这个对象的数据存储结构。
若是把线程池比做一个公司。公司会有正式员工处理正常业务,若是工做量大的话,会雇佣外包人员来工做。闲时就能够释放外包人员以减小公司管理开销。一个公司由于成本关系,雇佣的人员始终是有最大数。若是这时候还有任务处理不过来,就走需求池排任务。
这里逻辑稍微有点复杂,画了个流程图仅供参考
接下来,咱们看看如何添加一个工做线程的? addWork
有人或许会疑问 retry 是什么?这个是java中的goto语法。只能运用在break和continue后面。
接下来,咱们看看works是什么。
这两个钩子(beforeExecute,afterExecute)容许咱们本身继承线程池,作任务执行先后处理。有意思。 到这里,源代码分析到此为止。接下来作一下简单的总结。
最后但愿对你理解线程池有帮助。
都看到这里了,成神之路上,要不要一块儿?