Java并发编程和高并发基础三

八 线程池-需要关闭

https://www.cnblogs.com/jay-huaxiao/p/11454416.html

为什么使用线程池?
每次new Thread性能差;
线程缺乏统一的管理,可能无限制创建线程,导致占用系统过多资源而死机和OOM;
缺乏功能:如定时执行;

8.1 ThreadPoolExecutor

8.1.1 初始化参数讲解:

  1. corePoolSize:核心线程数,默认核心线程会一直存活,即使处于闲置状态也不会受keepAliveTime限制。
  2. maximumPoolSize:最大线程数,超过这个数的线程将被执行拒绝策略。当任务队列为没有设置大小的LinkedBlocking时,这个值无效。
  3. keepAliveTime:非核心线程的闲置超时时间,超过这个线程就会被自动回收。
  4. unit:指定keepAliveTime的单位,TimeUnit.SECONDS。将allowCoreThreadTimeOut设置为true时对corePoolSize生效。
  5. workQueue:任务队列,阻塞队列
  6. threadFactory:线程工厂,主要用来创建线程
  7. RejectedExecutionHandler:拒接策略,达到最大线程数的拒绝策略
    ThreadPoolExecutor.AbortPolicy:RejectedExecutionException异常。丢弃任务并抛出异常,默认的。
    ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。
    ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)
    ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务

总结:处理任务的优先级,核心线程数、任务队列、最大线程数,如果三者都满了,使用handler处理被拒绝的任务。
在这里插入图片描述

例子:这样的过程说明,并不是先加入任务就一定会先执行。假设队列大小为 10,corePoolSize 为 3,maximumPoolSize 为 6,那么当加入 20 个任务时,执行的顺序就是这样的:首先执行任务 1、2、3,然后任务 4 ~ 13 被放入队列。这时候队列满了,任务 14、15、16 会被马上执行,而任务 17~20 则会抛出异常。最终顺序是:1、2、3、14、15、16、4、5、6、7、8、9、10、11、12、13

监控系统里可以用,统计一下每分钟

  1. getTaskCount:线程池已执行和未执行的任务总数
  2. getCompletedTaskCount:已完成的任务数量
  3. getPoolSize:线程当前的线程数量
  4. getActiveCount:当前线程中正在执行任务的线程数量

8.1.2 线程池的状态

    private static final int RUNNING    = -1 << COUNT_BITS;
    private static final int SHUTDOWN   =  0 << COUNT_BITS;
    private static final int STOP       =  1 << COUNT_BITS;
    private static final int TIDYING    =  2 << COUNT_BITS;
    private static final int TERMINATED =  3 << COUNT_BITS;

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
几个重要的方法
execute(),submit(),shutdown(),shutdownNow()

  1. execute()实际上是Executor中声明的方法,在ThreadPoolExecutor进行了具体的实现,这个方法是ThreadPoolExecutor的核心方法,提交到线程池去执行。
  2. submit()是ExecutorService中声明的方法,在AbstractExecutorService就已经有了具体的实现,ThreadPoolExecutor并没有对其重写。有返回值Future。execute+Furture
  3. shoutdown():关闭线程池,等待任务都执行完毕
  4. shoutdownNow():关闭线程池,不等待任务都执行完毕

8.1.3 线程池队列和常用线程池Executors

8.1.3.1 ThreadPoolExecutor的BlockingQueue
  1. SynchronousQueue:同步队列,一个不存储元素的阻塞队列。每个插入操作必须等待另一个线程调用移除操作
  2. LinkedBlockingQueue:无边界队列,是一个基于链表的阻塞队列。可设置容量队列,不设置的话,将是一个无边界的阻塞队列。
  3. ArrayBlockingQueue :有界队列,是一个基于数组结构的有界阻塞队列。先进先出队列。
  4. DelayQueue:延迟队列,是一个任务定时周期的延迟执行的队列。根据指定的执行时间从小到大排序,否则根据插入到队列的先后队列。
  5. PriortyBlockingQueue:优先级队列,是具有优先级的无界阻塞队列。
8.1.3.2 Executors

创建线程池的工具

  1. Executors.newCachedThreadPool 可缓存线程的线程池。底层:SynchronousQueue
  2. Executors.newFixedThreadPool 固定数目线程的线程池,。底层:LinkedBlockingQueue
    在这里插入图片描述
  3. Executors.newScheduledThreadPool 定时及周期执行的线程池。底层:DelayQueue
  4. Executors.newSingleThreadPool 单线程执行,如果线程异常结束,会有另一个线程来取代它。底层:DelayedWorkQueue

8.1.4 Futrue

get方法:获取计算结果,一直会等待
cancel方法:还没计算完,可以取消计算过程
isDone方法:判断是否计算完
isCancelled方法:判断计算是否被取消

8.4 线程池合理配置

  1. cpu密集型任务,就需要尽量压榨cpu,参考值设置为cpu核数+1
  2. IO密集型的任务,参考值设置为2*CPU核数
    任务计算的时间和任务的调度时间差不多时,就不要用线程池了。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值