初学者';关于Java中RejectedExecutionException的问题
最近我开始学习基于Java的并发性,我在windows(jdk 11)上运行以下代码 代码摘自Java中的Thinging(第四个),我最初猜测是在提交所有任务之前驱动main()执行初学者';关于Java中RejectedExecutionException的问题,java,multithreading,Java,Multithreading,最近我开始学习基于Java的并发性,我在windows(jdk 11)上运行以下代码 代码摘自Java中的Thinging(第四个),我最初猜测是在提交所有任务之前驱动main()执行shutdown()的隐式线程,因为第一个任务成功执行,执行信息表明pool size=1,但这是不可能的,因为main()中的所有内容是按顺序执行的。关闭前应提交所有可调用对象 然后我将ThreadPool的类型更改为Executors.newFixedThreadPool(10),异常仍然发生,池大小仍然为1
shutdown()
的隐式线程,因为第一个任务成功执行,执行信息表明pool size=1
,但这是不可能的,因为main()中的所有内容是按顺序执行的。关闭前应提交所有可调用对象
然后我将ThreadPool的类型更改为Executors.newFixedThreadPool(10),异常仍然发生,池大小仍然为1
这是怎么发生的?包com.springboot.testapplication;
package com.springboot.testapplication;
import java.util.*;
import java.util.concurrent.*;
class TaskWithResult implements Callable<String> {
private int id;
public TaskWithResult(int id) {
this.id = id;
}
public String call() {
return "Result of TaskWithResult " + id;
}
}
public class TestCallable {
public static void main(String[] args) {
ExecutorService exec = Executors.newCachedThreadPool();
ArrayList<Future<String>> results = new ArrayList<Future<String>>();
for (int i = 0; i < 10; i++) {
results.add(exec.submit(new TaskWithResult(i)));
}
for (Future<String> fs : results) {
try {
System.out.println(fs.get());
} catch (InterruptedException e) {
System.out.println(e);
return;
} catch (ExecutionException e) {
System.out.println(e);
} finally {
exec.shutdown();
}
}
}
}
导入java.util.*;
导入java.util.concurrent.*;
类TaskWithResult实现可调用{
私有int-id;
公共任务WithResult(int id){
this.id=id;
}
公共字符串调用(){
返回“带有结果的任务结果”+id;
}
}
公共类TestCallable{
公共静态void main(字符串[]args){
ExecutorService exec=Executors.newCachedThreadPool();
ArrayList结果=新建ArrayList();
对于(int i=0;i<10;i++){
结果.添加(exec.submit(带有结果(i))的新任务);
}
未来财政司司长:结果{
试一试{
System.out.println(fs.get());
}捕捉(中断异常e){
系统输出打印ln(e);
返回;
}捕获(执行例外){
系统输出打印ln(e);
}最后{
exec.shutdown();
}
}
}
}
如果您更仔细地查看循环的,就会发现问题所在(尤其是当代码按常规缩进时):
for(int i=0;i<10;i++){
结果.添加(exec.submit(带有结果(i))的新任务);
未来财政司司长:结果{
试一试{
System.out.println(fs.get());
}捕捉(中断异常e){
系统输出打印ln(e);
返回;
}捕获(执行例外){
系统输出打印ln(e);
}最后{
exec.shutdown();
}
}
}
请注意,查询每个Future
的for
循环嵌套在提交任务的for
循环中。这意味着您提交一个任务,等待结果,关闭执行器,然后尝试提交另一个任务。以下内容可以解决您的问题:
for(int i=0;i<10;i++){
结果.添加(exec.submit(带有结果(i))的新任务);
}
executor.shutdown();//shutdown()允许执行已提交的任务
未来财政司司长:结果{
试一试{
System.out.println(fs.get());
}捕捉(中断异常e){
e、 printStackTrace();
返回;
}捕获(执行例外){
e、 printStackTrace();
}
}
我移动了executor.shutdown()
调用,因为这只需要在您提交上一个任务后发生一次。当然,如果您要继续重用executor,那么您就不会想关闭它
我还将System.out.println(e)
更改为e.printStackTrace()
。通常最好打印堆栈跟踪,而不仅仅是异常类型和消息(默认情况下,Throwable#toString()
返回异常类型和消息)。在像您的示例这样的短程序中,这可能并不明显,但堆栈跟踪在更复杂的应用程序中非常有价值,因为它直接指向引发异常的位置。有关详细信息,请参阅。代码中有一个小问题。找到下面的固定代码。
\\output:
Result of TaskWithResult 0
Exception in thread "main" java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.FutureTask@380fb434[Not completed, task = me.rexjz.a.TaskWithResult@21bcffb5] rejected from java.util.concurrent.ThreadPoolExecutor@3cda1055[Terminated, pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 1]
at java.base/java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2055)
at java.base/java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:825)
at java.base/java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1355)
at java.base/java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:140)
at javaBin/me.rexjz.a.TestCallable.main(TestCallable.java:22)
package com.springboot.testapplication;
import java.util.*;
import java.util.concurrent.*;
class TaskWithResult implements Callable<String> {
private int id;
public TaskWithResult(int id) {
this.id = id;
}
public String call() {
return "Result of TaskWithResult " + id;
}
}
public class TestCallable {
public static void main(String[] args) {
ExecutorService exec = Executors.newCachedThreadPool();
ArrayList<Future<String>> results = new ArrayList<Future<String>>();
for (int i = 0; i < 10; i++) {
results.add(exec.submit(new TaskWithResult(i)));
}
for (Future<String> fs : results) {
try {
System.out.println(fs.get());
} catch (InterruptedException e) {
System.out.println(e);
return;
} catch (ExecutionException e) {
System.out.println(e);
} finally {
exec.shutdown();
}
}
}
}