《Java并发编程之美-多线程之线程池》

本文深入探讨Java并发编程,讲解线程池ThreadPoolExecutor的工作原理,包括Executors工具类、ScheduledThreadPoolExecutor的延迟队列特性。同时,介绍了ScheduledFutureTask的执行模式。还讨论了线程同步器CountDownLatch的使用,以及在高并发场景下,如何避免日志打印对业务线程的影响,如使用LogBack的有界队列。文章还提及了线程安全问题,如ThreadLocal优化SimpleDateFormat的使用,以及创建线程和线程池时应指定业务相关的名称。最后,对比了Timer与ScheduledThreadPoolExecutor的异同,强调在实际开发中优先选择ScheduledThreadPoolExecutor。

《八:Java 并发包中线程池ThreadPoolExecutor原理》

线程池主要解决两个问题:
1. 一是当执行大量异步任务时线程池能够提供较好的性能。在不使用线程池时,每当需要执行异步任务时直接new 一个线程来运行,而线程的创建和销毁是需要开销的。线程池里面的线程是可复用的,不需要每次执行异步任务时都重新创建和销毁线程。
2. 二是线程池体提供了一种资源限制和管理的手段,比如可以限制线程的个数,动态新增线程等。每个ThreadPoolExecutor 也保留了一些基本的统计数据,比如当前线程池完成的任务数目等。
总结: 线程池也提供了许多可调用参数和可扩展性接口,以满足不同情景的需要,程序员可以更方便的Executors的工厂方法,比如newCachedThreadPool(线程池线程个数最多可达Integer.Max_value,线程自动回收),newFixedThreadPool(固定大小的线程池),newSingleThreadExecutor(单个线程)等来创建线程池。
线程池状态如下:
running: 接受新任务并且处理阻塞队列里的任务
shutdown: 拒绝新任务但是处理阻塞队列里的任务
stop: 拒绝新任务并且抛弃阻塞队列里的任务,同时会中断正在处理的任务。
tidying: 所有任务都执行完毕后当前线程池活动线程数为0,将要调用terminated方法。
terminated: 终止状态,terminated 方法调用完毕以后的状态。
线程池状态转换过程:
running->shutdown: 显式调用shutdown方法,或者隐式调用了finalize()方法里面的shutdown()方法
running|shutdown ->stop : 显式调用shutdownNow()方法。
shutdown->tidying: 当线程池和任务队列都为空时。
stop->tidying: 当线程池为空时。
tidying->terminated:  当terminated()hook方法执行完成时。
线程池中的参数
corePoolSize: 线程池核心线程个数
workQueue: 用于保存等待执行的任务的阻塞队列,比如基于数组的有界ArrayBlockingQueue,基于链表的无界LinkedBlockingQueue,最多只有一个元素的同步队列SynchronousQueue以及优先队列PriorityBlockingQueue等。
maximunPoolSize: 线程池最大线程数量
ThreadFactory:  创建线程的工厂。
RejectedExecutionHandler:  饱和策略。当队列满并且线程个数达到线程池最大线程数量后采取的策略,比如AbortPolicy(抛出异常),CallerRunsPolicy(使用调用者所在线程来运行任务),DiscardOldestPolicy(调用poll丢弃一个任务,执行当前任务),以及DiscardPolicy(默默丢弃,不抛出异常)。
 
keeyAliveTime: 存活时间。如果当前线程池中的线程数量比核心线程数量多,并且是闲置状态,则这些闲置的线程能存活的最大时间。
 
TimeUnit: 存活时间的时间单位。
Java通过Executors提供四种线程池,分别为:
newCachedThreadPool 创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
newScheduledThreadPool 创建一个定时性线程池,支持定时及周期性任务执行。
newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。

Executors 是个工具类,里面提供了好多静态方法,这些方法根据用户选择返回不同的线程池实例。ScheduledThreadPoolExecutor继承了ThreadPoolExecutor并实现了ScheduledExecutorService接口,线程池队列是DelayedWorkQueue,是一个延迟队列。ScheduledFutureTask是具有返回值的任务,继承自FutureTask。FutureTask的内部有一个变量state用来表示任务的状态,一开始状态为NEW。

线程池中的方法
execute方法: execute方法的作用是提交任务command到线程池进行执行。
worker 用户线程提交任务到线程池后,由worker来执行。
shutdown方法: 调用shutdown方法后,线程池就不会再接受新的任务了,但是工作队列里面的任务还是要执行的。该方法会立刻返回,并不等待队列任务完成再返回。
shutdownNow方法: 调用shutdownNow方法后,线程池就不会再接受新的任务了,并且会丢弃工作队列里面的任务,正在执行的任务会被中断,该方法会立刻返回,并不等待激活的任务执行完成。返回值为这时候队列里面被丢弃的任务列表。
awitTermination方法: 当线程调用awitTermination方法后,当前线程会被阻塞,直到线程池状态变成terminated才返回,或者等待时间超时才返回。
总结: 线程池巧妙的使用一个Integer类型的原子变量来记录线程池的状态和线程个数。通过线程池状态来控制任务的执行,每个worker线程可以处理多个任务。线程池通过线程的复用减少了线程创建和销毁的开销。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值