1. 线程池的作用

  • 升高资源耗费:通过重用曾经创立的线程来升高线程创立和销毁的耗费
  • 进步响应速度:工作达到时不须要期待线程创立就能够立刻执行
  • 进步线程的可管理性:线程池能够对立治理、调配、调优和监控

2. 线程池的组成

  • 线程池管理器(ThreadPool):用于创立并治理线程池,包含 创立线程池,销毁线程池,增加新工作;
  • 2、工作线程(PoolWorker):线程池中线程,在没有工作时处于期待状态,能够循环的执行工作;
  • 3、工作(Task):实现某个事件,它次要规定了工作的入口,工作执行完后的收尾工作,工作的执行状态等;
  • 4、工作队列(taskQueue):用于寄存没有解决的工作。提供一种缓冲机制。

3. 线程池的应用逻辑

4. 罕用线程池的品种

  • Java通过Executors提供了四种线程池,这四种线程池都是间接或间接配置ThreadPoolExecutor的参数实现的。

    • newCachedThreadPool:用来创立一个能够有限扩充的线程池,实用于负载较轻的场景,执行短期异步工作。(能够使得工作疾速失去执行,因为工作工夫执行短,能够很快完结,也不会造成cpu适度切换)
    SynchronousQueue:一个不存储元素的阻塞队列。每个插入操作必须等到另一个线程调用移除操作,否则插入操作始终处于阻塞状态,吞吐量通常要高于LinkedBlockingQueue。
    • 该线程池的工作机制是:
      1. 没有外围线程,间接向SynchronousQueue中提交工作
        1. 如果有闲暇线程,就去取出工作执行;如果没有闲暇线程,就新建一个
        1. 执行完工作的线程有60秒生存工夫,如果在这个工夫内能够接到新工作,就能够持续活下去,否则就拜拜
    • newFixedThreadPool:创立一个固定大小的线程池,因为采纳无界的阻塞队列,所以理论线程数量永远不会变动,实用于负载较重的场景,对以后线程数量进行限度。(保障线程数可控,不会造成线程过多,导致系统负载更为严重)
    • newSingleThreadExecutor:创立一个单线程的线程池,实用于须要保障程序执行各个工作。
    • newScheduledThreadPool:实用于执行延时或者周期性工作。

    4.1 ScheduledThreadPoolExecutor 增加工作提供了另外两个办法:

    scheduleAtFixedRate() :按某种速率周期执行
    scheduleWithFixedDelay():在某个提早后执行
    • 该线程池的工作机制是:

        1. 调用下面两个办法增加一个工作
        1. 线程池中的线程从 DelayQueue 中取工作(time 大于等于以后工夫的)
        1. 而后执行工作
        1. 执行完的工作批改time到指定工夫,重新加入队列

- 5. 线程池的参数

  • corePoolSize:线程池中的外围线程数

    • 外围线程会始终存活,即便是闲置状态
    • CPU密集型的工作(加密、解密、压缩、简单计算),个别core设置为CPU核数 + 1, 避免频繁的上下文切换;
    • IO密集型的工作(读写数据库、网络申请、文件读写),个别core设置为CPU核数 * 2
    • 具体要设置多少,还是测试、生产环境须要重复调试、批改
  • maximumPoolSize:线程池中最大线程数

    • 个别生产环境和core配的统一,避免线程池震荡
  • keepAliveTime:闲置超时工夫

    • poolSize > corePoolSize 后创立的为闲置线程 - 如果服务波峰之后有较长时间的波谷,能够思考尽快超时回收; 如果是密集的波峰,就要配久一点再超时
  • unit:keepAliveTime 超时工夫的单位(时/分/秒等)
  • workQueue:线程池中的工作队列
  • threadFactory:为线程池提供创立新线程的线程工厂
  • rejectedExecutionHandler:线程池工作队列超过最大值之后的回绝策略

    • java默认有4种实现, 如果不指定,默认抉择Abort, 上面排列由最消极到最踊跃 - DiscardPolicy, 抛弃工作,然而不抛出异样

      • DiscardOldestPolicy 抛弃队列最后面的工作,而后提交以后Task到队列尾部

        • AbortPolicy, 抛弃工作并抛出RejectedExecutionException
      • CallerRunsPolicy 由调用线程解决该工作

- 6. 为什么要应用阻塞队列

  • 避免线程无限度的创立、节约内存导致OOM or 节约CPU频繁进行上下文切换
  • 阻塞队列能够保障工作队列中没有工作时阻塞获取工作的线程,使得线程进入wait状态,开释cpu资源。
  • 当队列中有工作时才唤醒对应线程从队列中取出音讯进行执行。

参考:《2020最新Java根底精讲视频教程和学习路线!》
链接:https://juejin.cn/post/693865...