初学者';关于Java中RejectedExecutionException的问题

初学者';关于Java中RejectedExecutionException的问题,java,multithreading,Java,Multithreading,最近我开始学习基于Java的并发性,我在windows(jdk 11)上运行以下代码 代码摘自Java中的Thinging(第四个),我最初猜测是在提交所有任务之前驱动main()执行shutdown()的隐式线程,因为第一个任务成功执行,执行信息表明pool size=1,但这是不可能的,因为main()中的所有内容是按顺序执行的。关闭前应提交所有可调用对象 然后我将ThreadPool的类型更改为Executors.newFixedThreadPool(10),异常仍然发生,池大小仍然为1

最近我开始学习基于Java的并发性,我在windows(jdk 11)上运行以下代码

代码摘自Java中的Thinging(第四个),我最初猜测是在提交所有任务之前驱动main()执行
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();
            }
        }

    }
}