项目线程部分的重构
由于上次项目在生产在报了线程数过多的原因,决心把项目中涉及到开线程的任务全部排查一下,并把线程纳入自定义线程池中。
废话少说上代码:
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 后还是没有任务需要处理的话,收缩线程到核心线程数