ThreadPoolExecutor中運行線程名稱的修改

項目中使用到了ThreadPoolExecutor,這個是挺好的東西,線程池的實現。但有一點不太爽的是,用Jprofiler調試由它創建的線程的時候,看到的都是pool-1-thread-1\2\3\4之類的。這是它自身的默認規則產生的,pool代表這是池,-1-代表是第幾個ThreadPoolExecutor產生的,-thread-1是遞增的。

所以每次我都要點 Thread Dumps 去查看線程執行的具體的代碼與堆棧信息,推測是哪個地方出的問題。雖然說也能看出來,但很不直觀嘛。於是有了一個想法,能不能不要用它的默認名稱,由我自己的設定線程的名字,這樣就一目瞭然了。把idea和master王說了,覺得也是個好主意。當然就只是在開發階段有幫助,系統穩定上線後就沒有用了。

 Executors.defaultThreadFactory()是缺省的創建線程的實現。看下源碼,

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), defaultHandler);
之所以在工具中看到所有的線程都是以 pool- 開頭的,那是因爲人家就是寫死的。
    static class DefaultThreadFactory implements ThreadFactory {
        private static final AtomicInteger poolNumber = new AtomicInteger(1);
        private final ThreadGroup group;
        private final AtomicInteger threadNumber = new AtomicInteger(1);
        private final String namePrefix;

        DefaultThreadFactory() {
            SecurityManager s = System.getSecurityManager();
            group = (s != null) ? s.getThreadGroup() :
                                  Thread.currentThread().getThreadGroup();
            namePrefix = "pool-" +
                          poolNumber.getAndIncrement() +
                         "-thread-";
        }

        public Thread newThread(Runnable r) {
            Thread t = new Thread(group, r,
                                  namePrefix + threadNumber.getAndIncrement(),
                                  0);
            if (t.isDaemon())
                t.setDaemon(false);
            if (t.getPriority() != Thread.NORM_PRIORITY)
                t.setPriority(Thread.NORM_PRIORITY);
            return t;
        }
    }
我想要改成的格式是 pool-prjname-具體thread-1這種形式,如果說項目中所有代碼共用一個pool,我可以直接把 poolNumber.getAndIncrement() 換成想要的名稱。沒錯。但是具體thread呢?再搞一個參數,從上層傳遞進來替換嗎?最開始發現貌似可以的。當然了,這意味着原生的Executors不能用了,把所有代碼都copy到一個新類裏,可能還會關聯到其他類,也一併copy,如果不是關聯到很多類的話,還是可以的。如果一層又一層,就比較沒意思了。

使用方式:pool.taskPressIn(msgThread, "發送tmp"); 發送tmp就是我想要的具體thread的名稱。但通過工具多次觀察後,發現thread名稱不是傳進去的那個。認真考慮了newCachedThreadPool這個池,它是線程可複用的。當我提交了一個帶名稱的任務實例後,池子裏其實是有空閒的線程的,這些線程可能就是之前命過名的,直接運行實例了,名稱也就不會變了。

我最開始想着從池子中使用的線程入手,用的哪個就改哪個的名稱,由於跟代碼,想發現任務execute時,怎麼獲取線程的,master王想了一個辦法。

我們說一個線程在start後纔會執行run方法,run方法的執行表示這個task真正被線程運行了,這時線程的名稱也就確定了。所以可以在run的第一句加上       

Thread.currentThread().setName(ThreadPoolFairEx.renameThread(Thread.currentThread(), this.threadName));
Thread.currentThread()把當前的運行的線程傳進去,renameThread()是一個替換string的方法而已,把自定義的threadName替之。然後currentThread再setName。這樣就是這種效果




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章