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 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。这样就是这种效果 ThreadPoolExecutor中运行线程名称的修改_第1张图片




你可能感兴趣的:(JAVA,多线程,线程池)