Java并发编程系列30:抛出异常 java.util.concurrent.RejectedExecutionException

2年前 (2022) 程序员胖胖胖虎阿
305 0 0

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并发编程系列30:抛出异常 java.util.concurrent.RejectedExecutionException

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

相关文章

暂无评论

暂无评论...