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

2021-12-14 19:04:48 浏览数 (1)

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

代码语言:javascript复制
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 保存发货信息

跟一下源码:

代码语言:javascript复制
public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue) {
    this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
         Executors.defaultThreadFactory(), defaultHandler);
}

默认使用了线程池工厂类

代码语言:javascript复制
public static ThreadFactory defaultThreadFactory() {
   return new DefaultThreadFactory();
}

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

代码语言:javascript复制
/**
 * 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进去就行

代码语言:javascript复制
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类传进去

代码语言:javascript复制
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,例子是比较简单的,不过目的是通过例子,看看源码的实现原理

0 人点赞