【Java并发解析】线程池

线程池概况

减小新创建和回收线程的压力,线程数实现线程的复用。

线程池的创建

构造参数

在这里插入图片描述

  • corePoolSize 与 maxPoolSize: 前者是只要创建到了就不会减小,即使没有任务,但是maxPoolSize是在队列满了之后,可以灵活的增加新的线程,这个是线程池的上线。

  • keepAliveTime: 新增的非核心线程的最大存活时间,超过这个时间没有执行任务就会被回收。

  • workQueue: 1.直接队列 SynchronousQueue. 2. 无界 LinkedBlockingQueue 3. 有界 ArrayBlockingQueue

  • threadFactory:一般就是用默认的就可以Excutors.defaultThreadFactory()

线程的添加规则

在这里插入图片描述

线程池的调用逻辑

核心是ThreadPoolExecutor类,**这里源码值得一看。**涉及到一些函数的可以自己定义自己合适的线程池,如beforeExcutor等。

在这里插入图片描述

// 线程池调度的核心代码 在ThreadPoolExecutor类中的execute方法
    public void execute(Runnable command) {
        if (command == null)
            throw new NullPointerException();
        int c = ctl.get();     // 记录了线程池的状态和线程数
        if (workerCountOf(c) < corePoolSize) {
            if (addWorker(command, true)) // 执行的任务和,并且true表示不要超过核心线程的数量
                return;
            c = ctl.get();
        }
        if (isRunning(c) && workQueue.offer(command)) { // 检查是否线程池运行,因为前面判断了核心已经满了,这里把任务放入队列中
            int recheck = ctl.get();
            if (! isRunning(recheck) && remove(command))
                reject(command);
            else if (workerCountOf(recheck) == 0) // 防止没有线程正常运行
                addWorker(null, false);
        }
        else if (!addWorker(command, false)) // 线程满了,且队列满了,无法add进入循环
            reject(command);
    }

常用默认线程池

手动创建可以避免一些风险,并且需要和业务匹配。
以下是自动创建的线程池。

  1. ExecutorService threadpool = Executors.nexFixedThreadPool(4) 固定数量
  2. ExecutorService threadpool = Executors.nexSingleThreadPool() 单一
    以上两个都是LinkedBlockingQueue
  3. ExecutorService threadpool = Executors.nexCachedThreadPool() 可无限创建,core = 0 SynchronousQueue
  4. ExecutorService threadpool = Executors.nexScheduledThreadPool(10) 可以延迟运行 DelayedWorkQueue

线程数量的设计

CPU密集:线程数量为CPU的1-2倍
IO型:可以大于很多倍。线程数 = cpu*(1+等待时间/工作时间)

停止线程的方法

  • 实例方法shutdown():提交上去关闭的请求,但是主动权在线程池。更安全。可以用实例方法isShutdown()判断。或者isTerminated()判断, awaitTerminated()延迟判断是不是结束了线程池。

  • 实例方法shutdownNow: 立刻结束。中断所有正在执行的线程,并且返回没有进行的任务。

拒绝任务的策略

  • 拒绝时机:线程关闭后或者最大线程和工作队列容量已经饱和。

默认的四种拒绝策略:
在这里插入图片描述

线程池的状态

* RUNNING

线程池的组成与实现原理

线程池的组成

线程池包括:管理器(创建和停止),工作线程,任务队列(BlockingQueue),任务接口(Task)

Executor家族

线程池继承与实现的关系:
继承与实现的关系

辨析:

  • Executor:是一个顶层接口,只有一个方法Runnable()。执行任务的。
  • ExecutorServices:继承了Executor的接口,可以管理线程池,shutdown()等。
  • Executors:这是一个工具类。

线程池如何复用

每一个线程池拿到任务以后不断检测有没有新的任务,然后执行run

使用线程池的注意事项:

  1. 防止任务堆积
  2. 避免线程过度增加
  3. 排查线程泄露:线程执行完毕,无法被回收。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值