线程池通用管理类ThreadPools


在项目中使用线程池的时候,线程池也是一个对象,那么会有一个问题,要把这个线程池对象存在哪里呢?

一般来说有如下几种处理方案:
1、把线程池交给完成的Spring容器进行管理,在使用的时候通过@Autowired进行注入。
缺点:存在多个线程池时,需要使用@Qualifier手动指定beanName来确定使用哪个线程池,且手写beanName时没有自动提示,容易写错

2、在方法中,随用随时创建(明显不可取,如果这样还用线程池干啥?)

3、将线程池作为类的一个静态变量进行管理存储
可以写一个线程池管理类:

/**
 * 线程池管理类
 */
public class ThreadPools {

    /**
     * 样例线程池
     */
    public static final ThreadPoolExecutor exampleExecutor = new ThreadPoolExecutor(
            4, 4,
            0L, TimeUnit.MILLISECONDS,
            new LinkedBlockingQueue<Runnable>(),
            new NameableThreadFactory("example"));

    /**
     * 自定义名称线程工厂
     * 基于 {@link java.util.concurrent.Executors.DefaultThreadFactory} 进行修改
     */
    private static class NameableThreadFactory implements ThreadFactory {

        private final ThreadGroup group;
        private final AtomicInteger threadNumber = new AtomicInteger(1);
        private final String namePrefix;

        public NameableThreadFactory(String name) {
            SecurityManager s = System.getSecurityManager();
            this.group = s != null ? s.getThreadGroup() : Thread.currentThread().getThreadGroup();
            if (name != null && !"".equals(name.trim())) {
                this.namePrefix = "pool-" + name + "-thread-";
            } else {
                this.namePrefix = "pool-default-thread-";
            }
        }

        @Override
        public Thread newThread(Runnable runnable) {
            Thread t = new Thread(this.group, runnable, this.namePrefix + this.threadNumber.getAndIncrement(), 0L);
            if (t.isDaemon()) {
                t.setDaemon(false);
            }
            if (t.getPriority() != Thread.NORM_PRIORITY) {
                t.setPriority(Thread.NORM_PRIORITY);
            }
            return t;
        }

    }

}

建议给线程池中的线程指定一个名字,用于区分是哪个线程池的线程,所以这里参考DefaultThreadFactory自定义了一个NameableThreadFactory用于线程池中线程的创建。如果不需要的话也可以使用简单版本:

/**
 * 线程池管理类
 */
public class ThreadPools {

    /**
     * 样例线程池
     */
    public static final ThreadPoolExecutor exampleExecutor = new ThreadPoolExecutor(
            4, 4,
            0L, TimeUnit.MILLISECONDS,
            new LinkedBlockingQueue<Runnable>());

}

使用样例:

public class Test {

    public static void main(String[] args) {
        for (int i = 0; i < 10000; i++) {
            final int param = i;
            //Lambda表达式方式
            ThreadPools.exampleExecutor.submit(() -> {
                System.out.println(Thread.currentThread().getName()+" 执行参数:"+param);
            });
        }

        try {
            Thread.sleep(Integer.MAX_VALUE);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

在使用样例中,新任务的提交使用了Lambda表达式方式,并且在循环中新定义了一个final修饰的param参数用于i参数的传参。


觉得内容还不错?打赏个钢镚鼓励鼓励!!👍