前言
网上冲浪时刷到线程池的文章,想想看自己好像还没在实际场景中设置过线程名称,小小研究一下。
研究过程
默认命名
创建的线程都会有自己的名字,如果不设置,程序会给线程默认的名字,如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就是线程的名称。
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;
// ...省略
}
测试:
抽象实现
首先实现线程工厂构造器,主要构造线程工厂对象
@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
文章转载自:帅气的涛啊