文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

招行一面:Java 线程池的拒绝策略有哪些?如何选择?

2024-11-28 15:06

关注

Java的线程池类ThreadPoolExecutor位于java.util.concurrent 包中,它是一个灵活且广泛使用的线程池实现。线程池通过重用线程来减少线程创建和销毁的开销,提高应用程序的性能,线程池的基本组成如下:

拒绝策略的类型

ThreadPoolExecutor 提供了四种内置的拒绝策略:

AbortPolicy

AbortPolicy策略是直接抛出 RejectedExecutionException,不执行任务。适合在需要明确知道任务被拒绝时使用。

下面是AbortPolicy的源码实现:

public static class AbortPolicy implements RejectedExecutionHandler {
    public AbortPolicy() { }

    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        throw new RejectedExecutionException("Task " + r.toString() +
                                             " rejected from " +
                                             e.toString());
    }
}

使用场景:

CallerRunsPolicy

CallerRunsPolicy策略由提交任务的线程(通常是主线程)来执行该任务,通过降低任务提交速率来缓解压力。

下面是CallerRunsPolicy的源码实现:

public static class CallerRunsPolicy implements RejectedExecutionHandler {
    public CallerRunsPolicy() { }

    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        if (!e.isShutdown()) {
            r.run();
        }
    }
}

使用场景:

DiscardPolicy

DiscardPolicy策略是指直接丢弃无法执行的任务,不抛异常,也就是不对被丢弃的任务进行任何处理。

下面是DiscardPolicy的源码实现:

public static class DiscardPolicy implements RejectedExecutionHandler {
    public DiscardPolicy() { }

    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        // Do nothing
    }
}

使用场景:

DiscardOldestPolicy

DiscardOldestPolicy策略会丢弃队列中最旧的任务,然后尝试重新提交当前任务,这种策略通常用于保证新任务有机会被执行。

下面是DiscardOldestPolicy的源码实现:

public static class DiscardOldestPolicy implements RejectedExecutionHandler {
    public DiscardOldestPolicy() { }

    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        if (!e.isShutdown()) {
            e.getQueue().poll(); // discard oldest
            e.execute(r); // retry
        }
    }
}

使用场景:

自定义拒绝策略

除了内置策略,开发者可以实现 RejectedExecutionHandler 接口来定义自己的拒绝策略,通过这种方式,开发者可以根据具体需求来处理被拒绝的任务。下面是实现自定义策略的步骤:

代码示例如下:

public class CustomRejectedExecutionHandler implements RejectedExecutionHandler {
    @Override
    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
        // 自定义拒绝逻辑,例如日志记录或重新尝试
        log.warn("This is custom rejected: " + r.toString());
        // 可以选择重新提交任务或其他处理
    }
}

最后,我们再通过代码来展示如何创建一个线程池以及如何使用拒绝策略:

import java.util.concurrent.*;

public class ThreadPoolExample {
    public static void main(String[] args) {
        // 定义线程池的参数
        int corePoolSize = 2;
        int maximumPoolSize = 4;
        long keepAliveTime = 10;
        TimeUnit unit = TimeUnit.SECONDS;
        BlockingQueue workQueue = new ArrayBlockingQueue<>(2);

        // 创建线程池
        ThreadPoolExecutor threadPool = new ThreadPoolExecutor(
            corePoolSize,
            maximumPoolSize,
            keepAliveTime,
            unit,
            workQueue,
            new ThreadPoolExecutor.AbortPolicy() // 默认策略
            // new ThreadPoolExecutor.CallerRunsPolicy()
            // new ThreadPoolExecutor.DiscardPolicy()
            // new ThreadPoolExecutor.DiscardOldestPolicy()
            // new CustomRejectedExecutionHandler()
        );

        // 关闭线程池
        threadPool.shutdown();
    }
}

使用场景分析

不同的拒绝策略适合不同场景,下面是选择拒绝策略的一些参考因素:

总结

本文,我们通过源码分析了Java 线程池提供的拒绝策略,整体来说拒绝策略是比较简单的一个知识点,如果业务代码中使用了线程池,拒绝策略是必须掌握的一个知识点,开发者可以根据具体的场景选择合适的策略,甚至可以设计自定义策略来满足特定需求,避免因过载导致的系统崩溃。

来源:猿java内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯