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;
    
    // ...省略
    
}

测试:


抽象实现

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

@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】

posted @   帅气的涛啊  阅读(205)  评论(3编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示

目录