1、背景介绍
Java使用线程池newFixedThreadPool针对算法进行并发测试时,出现以下错误java.util.concurrent.RejectedExecutionException
Exception in thread "main" java.util.concurrent.RejectedExecutionException: Task com.cipherxxxcrypto.pertest.SM4PerTest$DecTask@76ed5528 rejected from java.util.concurrent.ThreadPoolExecutor@2c7b84de[Terminated, pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 4]
at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2063)
at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:830)
at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1379)
at com.cipherxxx.crypto.pertest.SM4PerTest.main(SM4PerTest.java:68)
java.util.concurrent.ThreadPoolExecutor@2c7b84de[Terminated, pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 4]
发现pool size 的值是0,active threads的值是0,
poolSize:线程池中当前线程的数量
active threads:活动线程数
queued tasks:任务队列数
2、分析ThreadPoolExecutor类
ThreadPoolExecutor类,引发java.util.concurrent.RejectedExecutionException,主要有两种原因:
1)、线程池显示的调用了shutdown()之后,再向线程池提交任务的时候,如果你配置的拒绝策略是ThreadPoolExecutor.AbortPolicy的话,这个异常就被会抛出来。
2)、当你的排队策略为有界队列,并且配置的拒绝策略是ThreadPoolExecutor.AbortPolicy,当线程池的线程数量已经达到了maximumPoolSize的时候,你再向它提交任务,就会抛出ThreadPoolExecutor.AbortPolicy异常。
3、分析本次多线程程序的原因
3.1、本次测试用的线程池是:newFixedThreadPool
1)该线程池未自定义拒绝策略,所以使用的默认拒绝策略,
线程池的默认拒绝策略为ThreadPoolExecutor.AbortPolicy,即直接抛出RejectedExecutionException异常.
直接抛出个RejectedExecutionException异常,也不执行这个任务了
2)线程数量固定的线程池(定长线程池),可控制线程最大并发数,超出的线程会在队列中等待。而队列LinkedBlockingQueue,LinkedBlockingQueue很大,任务不多的情况下,不会因为任务多导致调用到拒绝策略。
3.2、代码的最后结论
加密用的线程池对象和解密用的线程池对象都是同一个,加密时会调用到exs.shutdown();所以导致了线程池已经关闭了,还继续去请求任务。
【线程池调用了shutdown()之后,再向线程池提交任务的时候,如果你配置的拒绝策略是ThreadPoolExecutor.AbortPolicy的话,这个异常就被会抛出来。】
4、解决办法
在加密任务和解密任务中分别创建线程池对象。
原有:
//创建一个拥有固定线程数的线程池对象
ExecutorService exs = Executors.newFixedThreadPool(threadCount);
解决后:
//创建一个拥有固定线程数的线程池对象
ExecutorService exs;
String[] type={"sm4_encrypt","sm4_decrypt"};
for (String str :type) {
if (str=="sm4_encrypt") {//加密
exs = Executors.newFixedThreadPool(threadCount);
for (int i = 0; i < threadCount; ++i) {
//通过 ExecutorService 对象的 execute 方法将任务添加到线程去执行(获取到运行时间)
exs.execute(new EncTask(barrier, loopNum, i, sm4, plainData, key, iv));
}
}else {//解密
exs = Executors.newFixedThreadPool(threadCount);
for (int i = 0; i < threadCount; ++i) {
//通过 ExecutorService 对象的 execute 方法将任务添加到线程去执行(获取到运行时间)
exs.execute(new DecTask(barrier, loopNum, i, sm4, cipher, key, iv));
}
}
exs.shutdown();
}
Yet,不再报错,问题解决。
参考:https://blog.csdn.net/fen_fen/article/details/122833164
https://blog.csdn.net/fen_fen/article/details/122909142
https://blog.csdn.net/u010657094/article/details/110477635
https://baijiahao.baidu.com/s?id=1697728751268529678&wfr=spider&for=pc
转载请注明:Java并发编程系列30:抛出异常 java.util.concurrent.RejectedExecutionException | 胖虎的工具箱-编程导航