1.查看newCachedThreadPool线程池创建方法
创建线程池:
Executor cachedThread = Executors.newFixedThreadPool(1);
查看底层实现:
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue());
}
通过源码得出newCachedThreadPool的初始核心数是0最大核心数是使用的是 Integer.MAX_VALUE,SynchronousQueue是为队列。
2.使用ThreadPoolExecutor模拟newCachedThreadPool
public static void main(String[] args) {
int corePoolSize = 0;
int maximumPoolSize = Integer.MAX_VALUE;
long keepAliveTime = 60L;
SynchronousQueue syncQueue = new SynchronousQueue();
Executor cachedThread = new ThreadPoolExecutor(
corePoolSize,
maximumPoolSize,
keepAliveTime, TimeUnit.SECONDS,
syncQueue);
for (int i = 0; i < 50000; i++) {
cachedThread.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
});
}
}
3.执行查询系统资源占用情况
从图中可以看出CPU占用非常厉害,可能会导致机器卡死。
将程序改一下:
运行得出的参数:
可以看到workQueue的值一直是0,跑了10次worker数据为10
4、修改maximumPoolSize参数值为5
现执行程序
for (int i = 0; i < 50000; i++) {
cachedThread.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
});
}
执行结果:
从图中结果可以看出再执行到第5的时候就出现异常了。
再修改程序:每执行5个线程睡眠0.1秒
for (int i = 0; i < 50000; i++) {
//每执行5个线程睡眠0.1秒
if(i%5 == 0){
try {
System.out.println(“睡眠i==” +i);
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
cachedThread.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
});
}
执行结果:顺利完成且没有任何异常
5.结论
1.newCachedThreadPool最大的核心是int的最大值,如果有业务会在核心数内一直创建线程,导致CPU占用非常的高。
2.SynchronousQueue在此仅用于阻塞,不会进行何的缓存。
3.当创建的线程在业务未完成前,如果已达到最大核心数则不能再创建线程,如果再继续创建则会抛出异常。当可能worker有空的时候可以再次执行业为。可以看出有点像生产者消费模式,如果消费不及时者会不再继续生产,如果继续生产会导致失败。