线程池的好处

  1. 降低资源消耗:重复利用同一个线程可以执行多个不同的任务(Runnable)
  2. 提高响应速度:线程池中拥有创建好的线程,拿过来就用,不用new再start
  3. 提高线程的可管理性:避免这边用一下new一个,那边又new一个

线程池的实现原理

  1. 提交任务流程

image.png

  • 判断核心线程数是否满,不满创建新线程执行
  • 若核心线程数是满的,判断工作队列是否满,不满进入队列
  • 若工作队列也满,就看看是否可以创建临时线程
  • 最后都不行,就用指定的拒绝策略
  1. 工作线程的一个执行流程

image.png

线程池的创建

  • corePoolSize:可以使用prestartAllCoreThreads()方法,提前创建好
  • 任务队列
    • ArrayBlockingQueue:有界,数组
    • LinkedBlockingQueue:有界,链表,吞吐量高于上者
    • SynchronousQueueu:不存储元素的队列
    • PriorityBlockingQueue:优先级、无限
  • maximumPoolSize:使用无界队列的话就无效果了
  • ThreadFactory:创建线程的工厂,guava工具类中有可以快速创建的类
  • RejectedExecutionHandler:饱和策略
    • AbortPolicy:直接抛异常
    • CallerRunsPolicy:丢任务到线程池中的线程自己去执行
    • DiscardOldestPolicy:丢弃最老的任务
    • DiscardPolicy:直接丢弃当前新进任务
  • keepAliveTime:工作线程的存活时间,任务执行时间较短的可以调大时间
  • TimeUnit:指定上面时间的单位

提交任务

  1. execute:提交runnable
  2. submit:有返回值

关闭线程池

  1. shutdown
    1. 线程池状态置为shutdown
    2. 逐个中断运行中的线程(只是打标记)
  2. shutdownNow
    1. 线程池状态置为STOP
    2. 尝试停止或暂停任务
  3. 共性

    1. isShutdown()会返回true
    2. 所有任务关闭,线程池关闭,isTerminated返回true

      合理利用

  4. 建议使用有界队列

  5. Runtime.getRuntime().availableProcessors()方法获得当前设备的CPU个数
  6. CPU密集型:N+1
  7. IO密集型:2*N

线程池的监控

  1. 方法
    1. taskCount:需要执行任务的数量
    2. completedTaskCount:已经完成的
    3. largestPoolSize:是否满过
    4. getPoolSize:线程数
    5. getActiveCount:活动线程数
  2. 钩子
    1. beforeExecute
    2. afterExecute
    3. terminated