自定义线程池的名称(ThreadPoolExecutor)


目的:有时候为了快速定位出现错误的位置,在采用线程池时我们需要自定义线程池的名称。

1、创建ThreadFactory(ThreadPoolExecutor默认采用的是DefaultThreadFactory,可以参照代码)。

public class NamedThreadFactory implements ThreadFactory{

        private final AtomicInteger poolNumber = new AtomicInteger(1);

        private final ThreadGroup threadGroup;

        private final AtomicInteger threadNumber = new AtomicInteger(1);

        public  final String namePrefix;

        NamedThreadFactory(String name){
            SecurityManager s = System.getSecurityManager();
            threadGroup = (s != null) ? s.getThreadGroup() :
                    Thread.currentThread().getThreadGroup();
            if (null==name || "".equals(name.trim())){
                name = "pool";
            }
            namePrefix = name +"-"+
                    poolNumber.getAndIncrement() +
                    "-thread-";
        }

        @Override
        public Thread newThread(Runnable r) {
            Thread t = new Thread(threadGroup, r,
                    namePrefix + threadNumber.getAndIncrement(),
                    0);
            if (t.isDaemon())
                t.setDaemon(false);
            if (t.getPriority() != Thread.NORM_PRIORITY)
                t.setPriority(Thread.NORM_PRIORITY);
            return t;
        }
    }

2、创建线程池

 
//核心线程满了,则进入队列,队列满了,则创建新线程,当线程数达到最大线程数,则进入拒绝策略
static ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5,5,1,
            TimeUnit.MINUTES,new LinkedBlockingDeque<>(),new NamedThreadFactory("测试"));

3、测试代码

 static ThreadLocal<SimpleDateFormat>threadLocal = new ThreadLocal<SimpleDateFormat>(){
        @Override
        protected SimpleDateFormat initialValue() {
            return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        }
    };


 public static void main(String[] args) {
        threadPoolExecutor.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    System.out.println(threadLocal.get().parse("2019-10-22 16:59:00"));
                    throw new NullPointerException("sfa");
                } catch (ParseException e) {
                    e.printStackTrace();
                }
            }
        });
    }

4、结果

 补充:

1、参数解析

 2、拒绝策略

(1)、CallerRunsPolicy 

该任务被线程池拒绝,由调用execute方法的线程(如main线程)执行该任务。一般并发比较小,性能要求不高,不允许失败。但是,由于调用者自己运行任务,如果任务提交速度过快,可能导致程序阻塞,性能效率上必然的损失较大。

(2)、AbortPolicy 

丢弃任务,并抛出 RejectedExecutionException 异常。线程池默认的拒绝策略。必须处理好抛出的异常,否则会打断当前的执行流程,影响后续的任务执行。

(3)、DiscardOldestPolicy 

丢弃任务,不过也不抛出异常。

(4)、DiscardOldestPolicy 

当触发拒绝策略,只要线程池没有关闭的话,丢弃阻塞队列 workQueue 中最老的一个任务,并将新任务加入。


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM