自定義線程池的名稱(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