1、自定义线程池
如何创建线程池,核心是创建线程的 api:
ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit,
BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
示例:
package javaThreadPoolTrain;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
public class MyThreadPool {
private ThreadPoolExecutor pool = null;
public ExecutorService getCustomThreadPoolExecutor() {
return this.pool;
}
public void init() {
pool = new ThreadPoolExecutor(
3,
3,
30,
TimeUnit.MINUTES,
new ArrayBlockingQueue<Runnable>(5),
new CustomThreadFactory(),
new CustomRejectedExecutionHandler());
}
public void destory() {
if (pool != null) {
pool.shutdownNow();
}
}
private class CustomThreadFactory implements ThreadFactory {
private AtomicInteger count = new AtomicInteger(0);
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
String threadName = MyThreadPool.class.getName() + count.addAndGet(1);
System.out.println(threadName);
t.setName(threadName);
return t;
}
}
private class CustomRejectedExecutionHandler implements RejectedExecutionHandler {
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
// 记录异常
// 报警处理等
System.out.println("error.............");
throw new NullPointerException("enough");
}
}
//
// public static void test1() {
// throw new NullPointerException("test");
// }
public static void main(String[] args) {
try {
System.out.println("hello");
MyThreadPool myThreadPool = new MyThreadPool();
myThreadPool.init();
ExecutorService pool = myThreadPool.getCustomThreadPoolExecutor();
for (int i = 1; i < 10; i++) {
System.out.println("提交第" + i + "个任务!");
pool.execute(new Runnable() {
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("running=====");
}
});
}
//myThreadPool.destory();
} catch (Exception e) {
System.out.println("ss" + e);
}
}
}
2、 线程池监控
线程怎么说都是稀缺资源,对线程池的监控可以知道自己任务执行的状况、效率等。
2.1 java 内部提供的线程池指标
具体函数解析:
getCorePoolSize: 或者配置的核心线程数
getMaximumPoolSize: 或者最大线程数
getKeepAliveTime : 获取线程最长的休眠时间
getQueue: 获取工作队列
getThreadFactory(): 获取构建新线程的线程工厂类
getRejectedExecutionHandler():
getPoolSize(): 获取线程池中当前的线程数;
getActiveCount: 获取线程池中当前活跃的处于工作状态的线程数
getLargestPoolSize:获取线程池存活历史期间创建过的最大的线程数
getTaskCount:返回线程池总共执行过的任务数(包括完成的、正在执行的,以及还在队列中的)
getCompletedTaskCount:返回线程池总共完成过的任务数
对于这些指标,我们是可以通过metric 采集的方式动态采集出来,做到图表里,偏于我们实时查看线程池的使用情况,及时发现问题并且解决。
3、线程池配置动态修改技术
对于线程池,java 内部也提供了很多接口用于动态的修改线程池的配置,用于在线程池资源不足时,可以增加资源或者减少资源等
setKeepAliveTime:
setMaximumPoolSize:
setCorePoolSize
setRejectedExecutionHandler
setThreadFactory
最常用的应该就是set 核心线程数、最大线程数以及 线程最大存活时间
扩展:
除了在代码中显示触发一些条件进行set 外,我们还可以再外部动态的去修改线程池的参数,如通过zk 回调的方式,通过rpc 请求的方式等等
4、线程池隔离技术
线程池看似很美好,但也会带来一些问题。
如果我们很多业务都依赖于同一个线程池,当其中一个业务因为各种不可控的原因消耗了所有的线程,导致线程池全部占满。
这样其他的业务也就不能正常运转了,这对系统的打击是巨大的。对于不同的业务,我们需要做到线程池的隔离。
参考文献:
1、https://crossoverjie.top/2018/07/29/java-senior/ThreadPool/
2、