并发编程系列之自定义可以命名的线程池工厂类

Posted smileNicky

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了并发编程系列之自定义可以命名的线程池工厂类相关的知识,希望对你有一定的参考价值。

在使用多线程时候,有时候需要记录具体是哪些业务执行的,不过按照默认的情况,是会打印pool-1-thread-1这种类型的数据,所以有时候不能确定具体哪些业务线程执行的,可以先写一个线程池sample类,运行看看情况:


import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class ThreadPoolExample 

    public static void main(String[] args) 
        ExecutorService orderThreadPool = new ThreadPoolExecutor(2, 5,
                60L, TimeUnit.SECONDS,
                new ArrayBlockingQueue(5));
        ExecutorService sendThreadPool = new ThreadPoolExecutor(2, 5,
                60L, TimeUnit.SECONDS,
                new ArrayBlockingQueue(5));
        orderThreadPool.execute(new OrderTask());
        sendThreadPool.execute(new SendTask());
        // 避免内存泄露,记得关闭线程池
        orderThreadPool.shutdown();
        sendThreadPool.shutdown();
    

    static class OrderTask implements Runnable 
        @Override
        public void run() 
            System.out.println(String.format("thread name:%s",Thread.currentThread().getName()));
            System.out.println("保存订单信息");
        
    

    static class SendTask implements Runnable 
        @Override
        public void run() 
            System.out.println(String.format("thread name:%s",Thread.currentThread().getName()));
            System.out.println("保存发货信息");
        
    



控制台打印,不能定位是哪些线程

thread name:pool-1-thread-1
保存订单信息
thread name:pool-2-thread-1
保存发货信息

跟一下源码:

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue) 
    this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
         Executors.defaultThreadFactory(), defaultHandler);

默认使用了线程池工厂类

public static ThreadFactory defaultThreadFactory() 
   return new DefaultThreadFactory();

默认的线程池工厂,namePrefix = "pool-" +poolNumber.getAndIncrement() + "-thread-";,使用一个原子类,命名规则是这样的

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

所以,这边简单改下代码,传一个自定义的name进去就行


import org.springframework.util.StringUtils;

import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;

public class NamedThreadFactory 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;

    NamedThreadFactory(String threadFactoryName) 
        SecurityManager s = System.getSecurityManager();
        group = (s != null) ? s.getThreadGroup() :
                Thread.currentThread().getThreadGroup();
        threadFactoryName = StringUtils.isEmpty(threadFactoryName)
                ? "pool-"
                : threadFactoryName + "-";
        namePrefix = threadFactoryName + poolNumber.getAndIncrement()+ "-thread-";
    
    @Override
    public Thread newThread(Runnable r) 
        Thread t = new Thread(group, r,
                namePrefix + threadNumber.getAndIncrement(),
                0);
        // 守护线程
        if (t.isDaemon())
            t.setDaemon(false);
        // 优先级
        if (t.getPriority() != Thread.NORM_PRIORITY)
            // 标准优先级
            t.setPriority(Thread.NORM_PRIORITY);
        return t;
    


将自定义的NamedThreadFactory类传进去

ExecutorService orderThreadPool = new ThreadPoolExecutor(2, 5,
                60L, TimeUnit.SECONDS,
                new ArrayBlockingQueue(5),
                new NamedThreadFactory("orderPool"));

控制台打印

thread name:sendPool-2-thread-1
保存发货信息
thread name:orderPool-1-thread-1
保存订单信息

OK,例子是比较简单的,不过目的是通过例子,看看源码的实现原理

以上是关于并发编程系列之自定义可以命名的线程池工厂类的主要内容,如果未能解决你的问题,请参考以下文章

java之并发编程线程池的学习

alibaba-Java开发手册心得-一编程规约-6并发处理

并发编程系列:Java线程池的使用方式,核心运行原理以及注意事项

Java并发编程系列34 | 深入理解线程池(下)

原创Java并发编程系列33 | 深入理解线程池(上)

并发编程系列之如何正确使用线程池?