线程池交付策略、饱和处理策略、线程池如何关闭

Java并发工具ThreadPoolExecutor线程池使用讲解2: https://www.toutiao.com/a6635954508218253827/?log_from=88351ffeafe7e_1632474186416

public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads,
                                  0L, TimeUnit.MILLISECONDS,
                                  new LinkedBlockingQueue<Runnable>());
}

public static ExecutorService newSingleThreadExecutor() {
    return new FinalizableDelegatedExecutorService
        (new ThreadPoolExecutor(1, 1,
                                0L, TimeUnit.MILLISECONDS,
                                new LinkedBlockingQueue<Runnable>()));
}

public static ExecutorService newCachedThreadPool() {
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                  60L, TimeUnit.SECONDS,
                                  new SynchronousQueue<Runnable>());
}

A. 直接移交、B. 无界队列、C. 有界队列

① 当线程池不再被变量引用且线程池中线程数等于0时,线程池将自动关闭(利用Object.finalize实现)。

② 但是又因为默认情况下,线程池中对应corePoolSize的线程不会终止,所以线程池依然不能自动终止。可借助allowCoreThreadTimeOut(boolean)让核心worker线程空闲一段时间之后自动终止,这样线程池就可以自动关闭了。
③ 另外,也可以手动调用shutdown()来显式关闭线程池。还有一种比较暴力的关闭方式shutdownNow(),它除了不允许新任务再提交,还会中断正在执行任务的worker线程,让线程池立即关闭,所以可能导致数据丢失。shutdown()与shutdownNow()的区别与联系如下图所示,请耐心分析,应该好懂的(包括设置线程池关闭状态以禁止新任务提交、给worker发中断、丢弃任务队列等)。

============================

高度可靠系统,数据不再丢失?SynchronousQueue使用场景及实现: https://www.toutiao.com/a6651029973970715140/?log_from=63155271dc60d_1632474682357

生产者在把任务成功交至消费者之前也阻塞,其目的可能是为了保证任务数据的安全转移、防止丢失等。其中,SynchronousQueue(同步阻塞队列)是比较特殊的一种阻塞队列,特点如下:

队列存储空间始终等于0(1个元素也不保存)。
当没有消费者时,生产者往队列放数据会阻塞。
当没有生产者时,消费者从队列取数据会阻塞。

使用SynchronousQueue(或者TransferQueue)就可以避免这个问题,因为它会保证任务数据在生产者和消费者之间的直接转移,不再经过阻塞队列。SynchronousQueue实现了生产者和消费者线程在执行时间上的对齐.容量一定是0,只有等消费者到来之后,生产者才可以把数据放进去。而一旦放进去,就立即被消费者取走。

当生产者往队列提交数据(put操作)而此时没有消费者时,就往这个dual中放入一个"data"节点;当消费者从队列取数据(take操作)而此时没有生产者时,就往这个dual中放入一个"request"节点。"data"节点与"request"节点互相抵消(或称为匹配,match)。某种程度上,类似于表达式匹配问题的左右括号匹配。

posted @ 2021-09-24 19:52  TomStudio  阅读(133)  评论(0)    收藏  举报