zoukankan      html  css  js  c++  java
  • Java线程池-线程工厂ThreadFactory

    线程工厂ThreadFactory

    我们在项目开发额过程中,如果有很多地方使用多线程,那么给线程命名是十分有必要的,这样当出现问题的时候就比较容易排查

    创建线程池,使用默认的线程工厂

        /**
         * 创建线程池
         */
        public static final ThreadPoolExecutor pool =
                new ThreadPoolExecutor(
                        20,
                        100,
                        5,
                        TimeUnit.SECONDS,
                        new ArrayBlockingQueue<>(100)
                );
    测试
     public static void main(String[] args) {
            pool.execute(() -> {
                Integer integer = getOrderInfo();
                System.out.println(integer);
            });
            pool.shutdown();
        }
    
        private static Integer getOrderInfo(){
            try {
                List<Integer> list = new ArrayList<>();
                for (int i = 0 ; i < 10 ; i++){
                    list.add(i);
                }
                return list.get(11);
            }catch (Exception e){
                throw new IndexOutOfBoundsException("数组越界");
            }
        }

    上面程序发生异常,数组下标越界,我们发现线程的名称是pool-1-thread-1,pool代表是哪一个线程池,如果再启动一个线程池 就是pool-2,一直按照3,4,5,一直递增,thread-1则是线程,也是递增,thread-2,thread-2,但是当我们系统业务复杂,服务很多, 根据这个报错很难找出是哪里的问题。 img_1.png

    为线程设定名字

    我们首先看一下默认的ThreadFactory,

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

    不难看出在无参构造函数中使用了pool-作为前缀,那么这个我们可以自定义为自己的业务名称,ThreadFactory是一个接口,我们 实现它,并根据自己的需求去改就行,如下:

    我们在构造函数中传了一个threadName,然后拼接成我们想要的

    package thread.customthreadpool.threadFactory;
    
    import java.util.concurrent.Executors;
    import java.util.concurrent.ThreadFactory;
    import java.util.concurrent.atomic.AtomicInteger;
    
    /**
     * 自定义线程工厂
     *
     * 线程工厂可以设置线程信息
     */
    public class MyThreadFactory 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;
    
        /**
         * 构造函数传入我们想业务需要的线程名字threadName,方便发生异常是追溯
         * @param threadName
         */
        public MyThreadFactory(String threadName) {
            SecurityManager s = System.getSecurityManager();
            group = (s != null) ? s.getThreadGroup() :
                    Thread.currentThread().getThreadGroup();
            if (threadName == null || threadName.isEmpty()){
                threadName = "pool";
            }
            namePrefix = threadName +
                    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;
        }
    }

    然后将其加入线程池

        /**
         * 创建线程池
         */
        public static final ThreadPoolExecutor pool =
                new ThreadPoolExecutor(
                        20,
                        100,
                        5,
                        TimeUnit.SECONDS,
                        new ArrayBlockingQueue<>(100),
                        new MyThreadFactory("business")
                );

    当发生异常时,我们就能清晰的看到是哪一个模块的问题,能够快速的去排查 img.png

    生命不止,折腾不息
  • 相关阅读:
    面试官:软件测试没搞懂这些,哪里来的自信投简历? 刁钻问得高频的面试题(含答案)
    软件测试行业的职业素养?——《高级软件测试-高级软件测试分析师》第一章
    什么?你正在学web自动化测试?那这些Selenium的基本操作你了解过吗?
    没想到 Google 排名第一的编程语言,为什么会这么火?
    为什么大家都在用Fiddler?
    看了很多文章,就这篇说明白了什么是接口测试(含视频教程)
    Win 10 安裝 Docker 及相關設置
    Dynamics CRM
    Dynamics CRM
    Dynamics CRM
  • 原文地址:https://www.cnblogs.com/steakliu/p/15246661.html
Copyright © 2011-2022 走看看