Java线程命名问题解决

前言

网上冲浪时刷到线程池的文章,想想看自己好像还没在实际场景中设置过线程名称,小小研究一下。

研究过程

默认命名

创建的线程都会有自己的名字,如果不设置,程序会给线程默认的名字,如Thread-0

Thread t = new Thread(() -> {     System.out.println(Thread.currentThread().getName()); }); t.start(); // Thread-0 

设置线程名称,应当有个理由。现在一个项目中有订单相关线程池、有付款相关线程池,给线程命名,可以容易区分线程种类。如Thread-order-0Thread-fund-0

Thread内部实现原理

首先我们打开Thread类,属性name就是线程的名称。

public class Thread implements Runnable {     /* Make sure registerNatives is the first thing <clinit> does. */     private static native void registerNatives();     static {         registerNatives();     }          // 线程名字     private volatile String name;     private int            priority;     private Thread         threadQ;     private long           eetop;          // ...省略      } 

测试:

Java线程命名问题解决

抽象实现

首先实现线程工厂构造器,主要构造线程工厂对象

@Getter public class ThreadFactoryBuilder {          private String nameFormat;      public ThreadFactoryBuilder setNameFormat(String nameFormat) {         this.nameFormat = nameFormat;         return this;     }      public ThreadFactory build(){         return buildThreadFactory(this);     }      public static ThreadFactory buildThreadFactory(ThreadFactoryBuilder builder) {         final AtomicInteger counter = new AtomicInteger(0);         return r -> {             Thread t = new Thread(r);             // 这里设置了线程池名称,使用counter区分不同线程             t.setName(String.format(builder.getNameFormat(), counter.getAndIncrement()));             return t;         };     } } 

查看源码ExecutorService源码,发现预留了线程工厂的入参

// ExecutorService newFixedThreadPool 预留了ThreadFactory public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {     return new ThreadPoolExecutor(nThreads, nThreads,                                   0L, TimeUnit.MILLISECONDS,                                   new LinkedBlockingQueue<Runnable>(),                                   threadFactory); } 

测试代码正确性:

ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("测试命名线程-%d").build(); ExecutorService executor = Executors.newFixedThreadPool(5, threadFactory);  for (int i = 0; i < 10; i++) {     executor.execute(() -> {         try {             sleep(1000);         } catch (InterruptedException e) {             throw new RuntimeException(e);         }         System.out.println(Thread.currentThread().getName());     }); }  // 测试命名线程-3 // 测试命名线程-2 // 测试命名线程-1 // 测试命名线程-0 // 测试命名线程-4 // 测试命名线程-0 // 测试命名线程-2 // 测试命名线程-1 // 测试命名线程-3 // 测试命名线程-4 

最后/注意

本文只研究线程命名原理,可以直接使用开源实现【guava-ThreadFactoryBuilder】

发表评论

相关文章