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

举报
yd_273762914 发表于 2021/12/13 23:57:23 2021/12/13
【摘要】 在使用多线程时候,有时候需要记录具体是哪些业务执行的,不过按照默认的情况,是会打印pool-1-thread-1这种类型的数据,所以有时候不能确定具体哪些业务线程执行的,可以先写一个线程池sample类,...

在使用多线程时候,有时候需要记录具体是哪些业务执行的,不过按照默认的情况,是会打印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("保存发货信息");
        }
    }

}


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

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

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);
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

默认使用了线程池工厂类

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

  
 
  • 1
  • 2
  • 3

默认的线程池工厂,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;
    }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

所以,这边简单改下代码,传一个自定义的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;
    }
}


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

将自定义的NamedThreadFactory类传进去

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

  
 
  • 1
  • 2
  • 3
  • 4

控制台打印

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

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

文章来源: smilenicky.blog.csdn.net,作者:smileNicky,版权归原作者所有,如需转载,请联系作者。

原文链接:smilenicky.blog.csdn.net/article/details/121906428

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。