qwe 发表于 2025-2-7 01:26:50

Java线程命名问题解决

前言

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

默认命名

创建的线程都会有自己的名字,如果不设置,程序会给线程默认的名字,如Thread-0
Thread t = new Thread(() -> {    System.out.println(Thread.currentThread().getName());});t.start();// Thread-0设置线程名称,应当有个理由。现在一个项目中有订单相关线程池、有付款相关线程池,给线程命名,可以容易区分线程种类。如Thread-order-0、Thread-fund-0

Thread内部实现原理

首先我们打开Thread类,属性name就是线程的名称。
publicclass 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;      // ...省略    }
测试:


抽象实现

首先实现线程工厂构造器,主要构造线程工厂对象
@Getterpublic 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 预留了ThreadFactorypublic 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】
页: [1]
查看完整版本: Java线程命名问题解决