Try Everything Different In My Life.

「🔨实践」使用线程池

2020.06.15

多线程的支持是Java语言的一个特性,使用多线程可以提高程序的性能

Java线程池概貌

在Java开发中,池化的思想可以减少对象的频繁的创建,这种思想在软件开发中常用,比如数据库连接池。

在操作系统中,线程的创建也是非常消耗资源的操作,所有对于线程的创建应该慎重,Java提供了线程池来完成线程的创建。

在对象池化的思想中,可以简化成以下的模型

public class Pool<T>{

    private int poolSize;
    private List<T> pool = new ArrayList<>();

    Pool(ObjectFactory<T> factory){
        for(i = 0; i < poolSize; i++){
            T obj = factory.create();
            pool.add(obj)
        }
    }

    T getObj(){
       return obj; 
    }
    
    void release(T obj){
        ....   
    }
}

对象池是一个容器,这个容器来管理对象的创建和调用。但是线程池不是这种模型,线程池是一种生产-消费模型

本质上就是将任务(Thread)提交给线程池,然后线程池安排任务的执行,但是不是线程池都能完成提交的任务,所有线程池维护一个队列,当线程池中的线程不够的时候,所有的任务都是放在一个队列中,线程池中的线程完成任务之后消费队列中没有被消费的任务。当队列也满的时候,线程池就可以拒绝新的任务。

ThreadPoolExecutor创建的使用传入以下参数

  • int corePoolSize, 核心线程数
  • int maximumPoolSize, 最大线程数
  • long keepAliveTime, 线程存活时间
  • TimeUnit unit, 时间单位
  • BlockingQueue workQueue, 队列
  • ThreadFactory threadFactory, 线程工厂
  • RejectedExecutionHandler handler 拒绝策略

使用线程池

使用Executors来创建线程池

Java给我们提供了简单的线程池创建方法,使用Executors类可以创建4种线程池

线程池名称 特点
newSingleThreadExecutor 只有一个线程,保证任务按照顺序完成
newFixedThreadPool 线程池大小固定
newCachedThreadPool 线程池大小不固定
newScheduleThreadPool 按照周期来执行任务,线程池大小不固定

为什么阿里巴巴不允许使用Executors来创建线程池

使用Executors来创建线程池,队列是无界的,当有高并发的的情况下,一直往队列中添加会照成OOM

参考

🔗 Java线程池实现原理及其在美团业务中的实践 – 美团技术团队