自定义实现JAVA线程池的线程工厂类——ThreadFactory

在项目中使用JAVA线程池,日志打印的线程名为 pool-1-thread-1 格式,我们无法准确定位到是什么业务在使用线程。而线程池中线程的创建,由 ThreadFactory 接口来实现。那么我们自定义线程工厂类便可以解决该问题。

1. 测试代码

@Slf4j
public class ThreadTest {
    public static void main(String[] args) {
         * 使用Spring提供的ThreadFactory
        ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 1, 100
                , TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(), new CustomizableThreadFactory("demo-"));
        executor.execute(() -> {
            log.info("CustomizableThreadFactory数据...");
        ThreadPoolExecutor executor2 = new ThreadPoolExecutor(1, 1, 100
                , TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>());
        executor2.execute(() -> {
            log.info("executor2数据...");
        ThreadPoolExecutor executor3 = new ThreadPoolExecutor(1, 1, 100
                , TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>());
        executor3.execute(() -> {
            log.info("executor3数据...");
11:31:32.010 [pool-1-thread-1] INFO com.tellme.demo.ThreadTest - executor2数据...
11:31:32.010 [demo-1] INFO com.tellme.demo.ThreadTest - CustomizableThreadFactory数据...
11:38:17.462 [pool-2-thread-1] INFO com.tellme.demo.ThreadTest - executor3数据...

可以看到,当使用JAVA默认的线程池工厂类创建线程池时,pool-2...是递增的。

2. 默认的ThreadFactory

* The default thread factory 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(), if (t.isDaemon()) t.setDaemon(false); if (t.getPriority() != Thread.NORM_PRIORITY) t.setPriority(Thread.NORM_PRIORITY); return t;

注意:poolNumber是static变量,即全局递增。threadNumber为常量,每个对象递增。

我们重实现ThreadFactory,可以将线程池前缀传入。

3. 自定义的ThreadFactory

源码位置:com.alibaba.dubbo.common.utils.NamedThreadFactory

public class NamedThreadFactory implements ThreadFactory {
    protected static final AtomicInteger POOL_SEQ = new AtomicInteger(1);
    protected final AtomicInteger mThreadNum = new AtomicInteger(1);
    protected final String mPrefix;
    protected final boolean mDaemon;
    protected final ThreadGroup mGroup;
    public NamedThreadFactory() {
        this("pool-" + POOL_SEQ.getAndIncrement(), false);
    public NamedThreadFactory(String prefix) {
        this(prefix, false);
    public NamedThreadFactory(String prefix, boolean daemon) {
        mPrefix = prefix + "-thread-";
        mDaemon = daemon;
        SecurityManager s = System.getSecurityManager();
        mGroup = (s == null) ? Thread.currentThread().getThreadGroup() : s.getThreadGroup();
    @Override
    public Thread newThread(Runnable runnable) {
        String name = mPrefix + mThreadNum.getAndIncrement();
        Thread ret = new Thread(mGroup, runnable, name, 0);
        ret.setDaemon(mDaemon);
        return ret;
    public ThreadGroup getThreadGroup() {
        return mGroup;

便可以传入线程池名称和决定是否为守护线程。

4. ThreadFactory深入理解

  • 线程池是重复理利用线程资源,所以ThreadFactory的newThread方法是第一次创建线程时才会被调用;
  • 调用java.util.concurrent.ThreadFactory#newThread时创建子线程,是主线程执行的。