页面加载中
博客快捷键
按住 Shift 键查看可用快捷键
ShiftK
开启/关闭快捷键功能
ShiftA
打开/关闭中控台
ShiftD
深色/浅色显示模式
ShiftS
站内搜索
ShiftR
随机访问
ShiftH
返回首页
ShiftL
友链页面
ShiftP
关于本站
ShiftI
原版/本站右键菜单
松开 Shift 键或点击外部区域关闭
互动
最近评论
暂无评论
标签
寻找感兴趣的领域
暂无标签
    0
    文章
    0
    标签
    8
    分类
    10
    评论
    128
    功能
    深色模式
    标签
    JavaScript12TypeScript8React15Next.js6Vue10Node.js7CSS5前端20
    互动
    最近评论
    暂无评论
    标签
    寻找感兴趣的领域
    暂无标签
      0
      文章
      0
      标签
      8
      分类
      10
      评论
      128
      功能
      深色模式
      标签
      JavaScript12TypeScript8React15Next.js6Vue10Node.js7CSS5前端20
      未知歌曲
      未播放
      ♪ 暂无歌词 ♪
      随便逛逛
      博客分类
      文章标签
      复制地址
      深色模式
      AnHeYuAnHeYu
      Search⌘K
      博客
        暂无其他文档

        线程池(三)拒绝策略

        本文介绍了Java线程池的四种内置拒绝策略:AbortPolicy(抛出异常)、CallerRunsPolicy(调用线程执行)、DiscardPolicy(直接丢弃)和DiscardOldestPolicy(丢弃最旧任务),并通过源码解析了各策略的实现原理,同时说明了如何自定义拒绝策略以满足特定业务需求。

        July 2, 20246 分钟 阅读3 次阅读

        有的时候博客内容会有变动,首发博客是最新的,其他博客地址可能会未同步,认准https://blog.zysicyj.top

        可点击链接https://blog-1253652709.cos.ap-guangzhou.myqcloud.com//picgo/202401180921373.png 解答疑问

        线程池的拒绝策略

        线程池(ThreadPoolExecutor)是Java中用于管理和执行异步任务的一个强大工具。然而,在高并发场景下,线程池中的任务队列可能会被填满,从而导致新的任务无法被提交。这时,线程池就需要处理这些无法处理的任务。线程池的拒绝策略(RejectedExecutionHandler)就是为了解决这个问题而设计的。

        1. 线程池的拒绝策略简介

        Java的线程池提供了四种内置的拒绝策略,分别是:

        1. AbortPolicy:直接抛出 RejectedExecutionException,阻止系统正常工作。
        2. CallerRunsPolicy:由调用线程处理该任务。
        3. DiscardPolicy:直接丢弃任务,不予任何处理。
        4. DiscardOldestPolicy:丢弃队列中最旧的未处理任务,然后尝试重新提交被拒绝的任务。

        2. 详细源码解析

        接下来,我们通过源码深入了解每一种拒绝策略的具体实现。

        2.1 AbortPolicy

        public static class AbortPolicy implements RejectedExecutionHandler {
            public AbortPolicy() { }
        
            @Override
            public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
                // 抛出RejectedExecutionException异常
                throw new RejectedExecutionException("Task " + r.toString() + 
                                                     " rejected from " + 
                                                     e.toString());
            }
        }
        

        解析: - AbortPolicy策略会直接抛出 RejectedExecutionException 异常,通知调用者任务被拒绝,并且不会执行该任务。 - 这种策略适合对任务丢失敏感的场景,确保调用者能感知到任务未被执行。

        2.2 CallerRunsPolicy

        public static class CallerRunsPolicy implements RejectedExecutionHandler {
            public CallerRunsPolicy() { }
        
            @Override
            public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
                if (!e.isShutdown()) {
                    // 由调用线程来运行该任务
                    r.run();
                }
            }
        }
        

        解析: - CallerRunsPolicy策略不会丢弃任务,而是由提交任务的线程去执行该任务。 - 这种策略可以有效降低向线程池提交任务的速度,适合需要降低任务提交速率的场景。

        2.3 DiscardPolicy

        public static class DiscardPolicy implements RejectedExecutionHandler {
            public DiscardPolicy() { }
        
            @Override
            public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
                // 直接丢弃任务,不予处理
            }
        }
        

        解析: - DiscardPolicy策略在任务被拒绝时直接丢弃该任务,不进行任何处理,也不会抛出异常。 - 这种策略适合不需要确保每个任务都被执行的场景,比如日志记录等。

        2.4 DiscardOldestPolicy

        public static class DiscardOldestPolicy implements RejectedExecutionHandler {
            public DiscardOldestPolicy() { }
        
            @Override
            public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
                if (!e.isShutdown()) {
                    // 丢弃队列中最旧的任务
                    e.getQueue().poll();
                    // 尝试重新提交当前任务
                    e.execute(r);
                }
            }
        }
        

        解析: - DiscardOldestPolicy策略会丢弃队列中最旧的未处理任务,然后尝试重新提交被拒绝的任务。 - 这种策略适合优先处理最新任务的场景。

        3. 自定义拒绝策略

        除了以上四种内置策略,开发者还可以实现 RejectedExecutionHandler 接口,定义自己的拒绝策略。以下是一个自定义拒绝策略的示例:

        public class CustomRejectPolicy implements RejectedExecutionHandler {
            @Override
            public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
                // 自定义处理逻辑,例如记录日志或持久化任务
                System.out.println("Custom reject policy: " + r.toString() + " rejected");
                // 可以选择抛出异常或者执行其他操作
                throw new RejectedExecutionException("Custom policy: Task " + r.toString() + " rejected from " + e.toString());
            }
        }
        

        4. 总结

        线程池的拒绝策略在高并发场景下尤为重要。根据具体应用场景选择合适的拒绝策略,可以有效地控制系统的稳定性和任务处理效率。了解并掌握这些策略的实现原理,有助于开发者在实际项目中灵活运用。

        通过上述内容,我们详细解析了Java线程池的四种内置拒绝策略的源码实现及其适用场景。希望这些内容能帮助你更好地理解和应用线程池的拒绝策略。

        最后更新于 July 2, 2024
        On this page
        暂无目录