项目线程部分的重构

由于上次项目在生产在报了线程数过多的原因,决心把项目中涉及到开线程的任务全部排查一下,并把线程纳入自定义线程池中。

废话少说上代码:

1.自定义帮助类

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

/**
*自定义线程池的帮助类
*/
public class ThreadPoolHelper{

private static String RUNPOOL_NAME_TIME = "runTimePool";
//自定义线程池
private static ThreadPoolExecutor runTimePool = new ThreadPoolExecutor(
   2, 5, 1, TimeUnit.MINUTES, new ArrayBlockingQueue<>(10),new MyThreadFactory(RUNPOOL_NAME_TIME) , new ThreadPoolExecutor.AbortPolicy());
 
 public static ThreadPoolExecutor getRunTimeThreadPool() {
  //自定义设置线程池的特性
  //线程池在空闲时可以回收核心线程
  runTimePool.allowCoreThreadTimeOut(true);
  //声明线程池后直接启动全部核心线程
  runTimePool.prestartAllCoreThreads();
  return runTimePool;
 }
 

}

2.自定义的工厂类,可以根据自己的需求改造,可参考Executors.defaultThreadFactory()源码里的方法

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

/**
 * 自定义线程工程
 * Executors.defaultThreadFactory() ---创建线程池的默认工程
 */
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;
      
     //此处新增了自定义线程池的名称,可根据自己的需求,做改造
     MyThreadFactory(String threadPoolName) {
          SecurityManager s = System.getSecurityManager();
          group = (s != null) ? s.getThreadGroup() :
                                Thread.currentThread().getThreadGroup();
          namePrefix = threadPoolName+":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;
      }



}

3.将线程放入线程池调用

ThreadPoolHelper.getRunTimeThreadPool().execute(timeThread);
//此处的timeThread就不在详述了,新建个线程类即可

4.总结
线程池帮助类,可以根据实际的需求,新建不同的线程池;
将线程纳入线程池也是比较规范和业内认可的做法;
当然注意多线程带来的问题,此处就不啰嗦了。

以下线程池工作行为的总结

corePoolSize:核心线程数
maximumPoolSize:线程池最大线程数
keepAliveTime:等待时间
unit:等待时间的单位
workQueue:工作队列
threadFactory:线程工厂,负责创建线程
handler:拒绝策略,在线程出错时的应对措施

1.不会初始化 corePoolSize 个线程,有任务来了才创建工作线程;当核心线程满了之后不会立即扩容线程池,而是把任务堆积到工作队列中;

2.当工作队列满了后扩容线程池,一直到线程个数达到 maximumPoolSize 为止;

3.如果队列已满且达到了最大线程后还有任务进来,按照拒绝策略处理;

4.当线程数大于核心线程数时,线程等待 keepAliveTime 后还是没有任务需要处理的话,收缩线程到核心线程数