ThreadPoolExecutor线程池原理(太细了)

一、什么是ThreadPoolExecutor

ThreadPoolExecutor是一个线程池,最多可使用7个参数来控制线程池的生成。
使用线程池可以避免创建和销毁线程的资源损耗,提高响应速度,并且可以管理线程池中线程的数量和状态等等。
阿里巴巴手册中也推荐使用该线程池,因为Executors创建缓存线程池时,最大线程数是Integer.MAX_VALUE,可能导致堆栈溢出。而且使用ThreadPoolExecutor创建线程池可以让开发者更好理解线程池原理。

二、使用线程池的优点

1.减少系统资源消耗

无须重复创建和销毁线程,减少了线程创建和销毁造成的资源消耗。

2.提高响应速度

创建好的线程会驻留在线程池中,无需创建新线程执行任务,因而提高了响应速度。

3.提高了线程的可管理性。

线程池可以控制线程的数量,可以选择拒绝策略,可以监控和管理线程的状态,控制并发量等等。
这些都是自己创建线程难以做到的。

三、线程池原理

3.1 线程池的7个参数

1)corePoolSize 核心线程数

线程池常驻线程数量

2)maximumPoolSize 最大线程数

最大可存在的线程数量

3)keepAliveTime 非核心线程的存活时间

非核心线程空闲时,可以停留的时间

4)unit 存活时间的单位

非核心线程空闲时,可以停留的时间的单位

5)workQueue 阻塞队列

线程都在使用中时,可以将任务保存在阻塞队列中,可以设置队列的长度。

6)threadFactory 线程创建工厂

可以选择创建线程的工厂

7)handler 拒绝策略

当线程池无法存放更多任务时,处理这些过多的任务的策略

3.2 线程池执行任务的流程

public void execute(Runnable command) {
    if (command == null)
        throw new NullPointerException();

	
    int c = ctl.get();
    //判断工作线程数是否小于核心线程数
    if (workerCountOf(c) < corePoolSize) {
    	//是,创建一个新线程
        if (addWorker(command, true))
            return;
        c = ctl.get();
    }
    //否,将任务尝试添加到阻塞队列中,如果队列满了则会添加失败。
    if (isRunning(c) && workQueue.offer(command)) {
        int recheck = ctl.get();
        //判断线程池状态是否在运行中,不在运行中时,删除该任务
        if (! isRunning(recheck) && remove(command))
        	//不在运行中时,执行拒绝策略
            reject(command);
        //判断工作线程数是否为0
        else if (workerCountOf(recheck) == 0)
        	//为0的场合,尝试创建新线程
            addWorker(null, false);
    }
    //添加失败的场合,尝试创建一个新线程
    else if (!addWorker(command, false))
    	//如果添加失败,执行拒绝策略
        reject(command);
}
  1. 当执行一个任务时,首先会判断工作线程数是否小于核心线程数
    1.1. 如果小于核心线程数,则创建一个新线程来执行该任务。执行完毕。
  2. 如果大于核心线程数,则尝试将任务放入阻塞队列中。
    2.1. 如果成功放入阻塞队列,待有空闲的线程时,空闲线程会从阻塞队列中获取任务并执行。执行完毕。
  3. 如果放入失败,表示阻塞队列已满,此时会尝试创建一个新线程来执行该任务。
    3.1. 如果当前线程数小于最大线程数,则会创建新线程来执行该任务。执行完毕。
    3.2. 如果工作线程数等于最大线程数,则不会创建新线程,尝试创建失败。此时会执行拒绝策略执行完毕。

四、Executors提供的常用线程池

4.1 Executors.newFixedThreadPool

一个固定数量的线程池,可以通过传入的参数int nThreads来控制线程池的线程数量。(核心线程数和最大线程数相同)

public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }

4.2 Executors.newSingleThreadExecutor

一个线程数只有1的线程池。可以保证任务的顺序执行。

public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }

4.3 Executors.newCachedThreadPool

缓存线程池,新创建的线程会在该线程池中缓存60秒。可以提高短期异步任务的性能。
注意,最大线程数是Integer.MAX_VALUE,高并发的场合下,可能会创建大量线程。

public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }

4.4 Executors.newScheduledThreadPool

定时任务线程池,使用该线程池可以定时执行任务。

public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
        return new ScheduledThreadPoolExecutor(corePoolSize);
    }
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

笑我归无处

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值