首页 > 编程语言 >java线程池使用小技巧:自定义拒绝策略

java线程池使用小技巧:自定义拒绝策略

时间:2023-03-12 16:24:38浏览次数:31  
标签:java 自定义 Thread 线程 new factoryName public

java 线程池默认提供了几种拒绝策略:

这几个策略都实现了RejectedExecutionHandler,拿DiscardOldestPolicy来说,查看源码:

核心代码只有2行:

  • e.getQueue().poll() 从列表里弹出1个(最早的)任务,以便让队列空出1个位置
  • e.execute(r) 新任务放入队列执行

从这段代码来看,如果有任务被丢弃(即:从队列里弹出了),不会有任何报错,也没有日志可查,实际使用中不太方便监控这种情况。

 

我们可以参考这段源码,自定义策略:

import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;

public class CustomDiscardPolicy implements RejectedExecutionHandler {

    //额外传入1个名称,方便打日志或埋点监控时,定位问题
    private String factoryName = "";

    public CustomDiscardPolicy(String factoryName) {
        this.factoryName = factoryName;
    }

    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        if (!e.isShutdown()) {
            Runnable poll = e.getQueue().poll();
            //这里可以加一些自己的处理(比如:埋点监控)
            System.err.println("[" + this.factoryName + "]task will be discard:" + poll);
            e.execute(r);
        }
    }
}

当然,这里出于演示目的,只打了一行错误信息,实际应用中大家可以埋点发到kafka之类(以便后续做实时监控预警)。

测试一下:

    @Test
    public void testThreadPool() throws InterruptedException {
        final ThreadFactory DEMO_THREAD_FACTORY = new ThreadFactoryBuilder().setNameFormat("demo-POOL-%d").build();

        final ExecutorService DEMO_POOL = new ThreadPoolExecutor(1, 2, 300L, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<>(5), DEMO_THREAD_FACTORY, new CustomDiscardPolicy("demo-POOL"));

        for (int i = 0; i < 10; i++) {
            DEMO_POOL.submit(() -> {
                try {
                    System.out.println(Thread.currentThread().getId() + " ready!");
                    //假设线程干活,需要一段时间
                    Thread.sleep(500);
                    System.out.println("\t" + Thread.currentThread().getId() + " done!");
                } catch (Exception e) {
                }
            });
        }
        //等一会儿,让线程池都跑完,再结束main
        Thread.sleep(10000);
    }

提交了10个任务,线程池必然饱和(10>2+5),会丢弃一些早期任务,输出如下:

从输出看,丢了3个任务,符合预期。

标签:java,自定义,Thread,线程,new,factoryName,public
From: https://www.cnblogs.com/yjmyzz/p/how_to_customize_thread_pool_reject_policy.html

相关文章

  • 韩顺平java学习笔记——概述
    Java执行流程分析Java文件(源文件)—javac编译->.class文件(字节码文件)--java运行->结果什么是编译Javachello.java1、 有了java源文件,通过编译器将其变异成JVM可以......
  • 韩顺平java——常用的换义字符
    Java常用的转义字符1、\t:一个制表位,实现对其功能2、\n:换行符3、\:一个4、\”:一个”5、\’:一个’6、\r:一个回车System.out.println(“韩顺平教育\r北京”);初学java......
  • Java算法——字符串
    344.反转字符串编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组s的形式给出。不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用O(1)......
  • 注解处理器 2:java 注解处理器
    前篇文档:注解处理器1:javax.lang.model包讲解概览注解处理器(AnnotationProcessorTool)是javac的一个工具,它用来在编译时扫描和处理注解(Annotation)。其生效的时间......
  • java基础五-序列化和反序列化
     序列化和反序列化序列化:将对象转换为字节序列的过程反序列化将字节序列恢复为对象的过程实现序列化实现Serializable接口-创建对象输出流-调用writeObject()方法-......
  • [JS JavaScript] 使用CryptoJS库对给定的加密字符串进行解密
    本代码可以使用在Web中,或者其他可以出入密码的场景在需要解密的信息不大的情况下,可以将加密后的信息放入到JS中,在输入密码后,对加密后的信息进行解密在vue中,可以很方便的......
  • java8新特性-引用流-max,min
    例子:List<User>users=newArrayList<>();users.add(newUser("张三",30));users.add(newUser("李四",34));users.add(newUser("王五",20));......
  • UE5 自定义编辑器主题
    UE5新增了Editor->EditorPreference->Appearence->ActiveTheme配置,支持用户自定义颜色主题调到自己看起来舒服就行参考:HowToChangeColorThemei......
  • 线程死锁问题以及递归锁解法
    fromthreadingimportThread,Lock,RLockimporttimemutexA=Lock()muteXB=Lock()'''#将上述的mutexA=Lock()mutexB=Lock()#换成mutexA=mutexB=RLoc......
  • mysql-connector-java版本大于5,项目启动连接数据库报错
    项目启动连接数据库报错如下2023-02-0822:44:23.491ERROR23596---[reate-951000054]com.alibaba.druid.pool.DruidDataSource:createconnectionSQLException,......