动态拓展容量 触发方式,我们可以通过 apollo 配置或者通过延迟任务定期扫描自动拓展,可以通过这种方式对生产环境线程池参数进行动态优化。,线程池的使用可以提高我们并发程序线程复用,以及提供对线程的管理能力。提高线程的利用率,提升性能。但是对于一些场景我们需要知道当前线程池中提交的任务是否执行完毕,我们可以通过一下4种方式判断。,threadPool.isTerminated() 常用来判断线程池是否结束,结束了为TRUE. 使用 threadPool.isTerminated() 方法,必须在shutdown()方法关闭线程池之后才能使用,否则isTerminated()永不为TRUE,线程将一直阻塞在该判断的地方,导致程序最终崩溃。,我们可以通过判断线程池中的计划执行任务数和已完成任务数,来判断线程池是否已经全部执行完,如果计划执行任务数=已完成任务数,那么线程池的任务就全部执行完了,否则就未执行完。,方法解析:,PS: 此实现方法的优点是无需关闭线程池。 它的缺点是getTaskCount() 和getCompletedTaskCount(),返回的是一个近似值,因为线程池中的任务和线程的状态可能在计算过程中动态变化,所以它们两个返回的都是一个近似值。,CountDownLatch 是一个栅栏类似计数器,我们创建了一个包含 N 个任务的计数器,每个任务执行完计数器 -1,直到计数器减为 0 时,说明所有的任务都执行完了,CountDownLatch 写法很优雅,且无需关闭线程池,但它的缺点是只能使用一次,CountDownLatch创建之后不能被重复使用,也就是说 CountDownLatch 可以理解为只能使用一次的计数器。,执行结果:,
,**CyclicBarrier 构造方法核心参数: **,await 方法: 在 CyclicBarrier 上进行阻塞等待,当调用此方法时 CyclicBarrier 的内部计数器会 -1,直到发生以下情形之一: 在 CyclicBarrier 上等待的线程数量达到 parties,也就是计数器的声明数量时,则所有线程被释放,继续执行。 当前线程被中断,则抛出 InterruptedException 异常,并停止等待,继续执行。 其他等待的线程被中断,则当前线程抛出 BrokenBarrierException 异常,并停止等待,继续执行。 其他等待的线程超时,则当前线程抛出 BrokenBarrierException 异常,并停止等待,继续执行。 其他线程调用 CyclicBarrier.reset() 方法,则当前线程抛出 BrokenBarrierException 异常,并停止等待,继续执行。,reset 方法: 使得CyclicBarrier回归初始状态,直观来看它做了两件事: 如果有正在等待的线程,则会抛出 BrokenBarrierException 异常,且这些线程停止等待,继续执行。 将是否破损标志位 broken 置为 false。 优缺点分析 CyclicBarrier 从设计的复杂度到使用的复杂度都高于 CountDownLatch,相比于 CountDownLatch 来说它的优点是可以重复使用(只需调用 reset 就能恢复到初始状态),缺点是使用难度较高。,使用 isTerminated 方法判断:通过判断线程池的完成状态来实现,需要关闭线程池,一般情况下不建议使用。,使用 getCompletedTaskCount 方法判断:通过计划执行总任务量和已经完成总任务量,来判断线程池的任务是否已经全部执行,如果相等则判定为全部执行完成。但因为线程个体和状态都会发生改变,所以得到的是一个大致的值,可能不准确。,使用 CountDownLatch 判断:相当于一个线程安全的单次计数器,使用比较简单,且不需要关闭线程池,是比较常用的判断方法。,使用 CyclicBarrier 判断:相当于一个线程安全的重复计数器,但使用较为复杂,所以日常项目中使用的较少。,对于线程池提交速率限制,我们可以通过信号量进行限制,这样可以避免触发线程池的拒绝策略,将逻辑处理能力限制功能前置,可以做到线程池的职责单一,负责提交而去做额外的事情。 下面是一个简单的例子:,执行结果:,
,我们可以看到,我们同一个时间只能获取两个信号量,也就是两个线程能进行执行,如果新进入线程调用 semaphore.acquire();方法进入线程阻塞,需要等待有信号量释放过后才能进入新的调用。释放方法 semaphore.release();.,Java 单机延迟任务我们可以通过, Delayed + DelayQueue� 实现:,实现 Delayed 接口 ,自定义消息体/延迟任务对象,创建任务执行线程、方法,去调用 delayQueue获取延迟任务对象。 通常情况下我们可以定义一个独立的线程去处理这些任务。,测试代码如下:,输出结果如下:,
© 版权声明
文章版权归作者所有,未经允许请勿转载。