当前位置: 首页 > 面试题库 >

为什么并行ForkJoinPool会使我的异常倍增?

易俊远
2023-03-14
问题内容

假设我有如下代码:

Future<Object> executeBy(ExecutorService executor) {
    return executor.submit(() -> {
        throw new IllegalStateException();
    });
}

使用ForkJoinPool#commonPool时没有问题,但是当我使用并行时ForkJoinPool它会加倍IllegalStateException。例如:

executeBy(new ForkJoinPool(1)).get(); 
//                              ^--- double the IllegalStateException

Q1 :为什么并行性会在其中发生ForkJoinPool两倍?Exception``Callable

Q2 :如何避免这种奇怪的行为?


问题答案:

如果在工作线程中引发了异常,则Fork /
Join池通常会尝试在调用者线程内重新创建异常,并将原始异常设置为其原因。这就是您认为的“加倍”。当您仔细查看堆栈跟踪时,您会注意到这两个异常之间的差异。

公用池在这方面没有什么不同。但是公共池允许调用者线程在等待最终结果时参与工作。因此,当您将代码更改为

static Future<Object> executeBy(ExecutorService executor) {
    return executor.submit(() -> {
        throw new IllegalStateException(Thread.currentThread().toString());
    });
}

您会注意到,经常发生的情况是,调用者线程get()在该方法中的调用速度更快,并且在该方法中进行工作窃取的速度超过了工作线程可以接任务的速度。换句话说,您的供应商已在主线程/调用者线程中执行,在这种情况下,不会重新创建异常。

可以通过抛出一个异常类型来轻松禁用此功能,该异常类型没有F / J可以使用的匹配公共构造函数,例如下面这个整洁的内部类:

static Future<Object> executeBy(ExecutorService executor) {
    return executor.submit(() -> {
        throw new IllegalStateException() {
                @Override
                public String toString() {
                    String s = getClass().getSuperclass().getName();
                    String message = getLocalizedMessage();
                    return message!=null? s+": "+message: s;
                }
            };
    });
}


 类似资料:
  • 这是我的申请 数据源:类型:com.zaxxer.hikari.HikariDataSource主要: 这是我的入门: 这是我的例外: 2017-11-21 10:10:33.126线程“main”中的表现:java.lang.运行时异常: java.lang.ClassCastException: 无法将 com.mysql.cj.jdbc.Driver to javax.sql.DataSou

  • 请问为什么第13行的错误是未报告的异常,必须捕获pr声明要抛出

  • 将并行流执行提交到您自己的forkJoinpool:yourfjp.submit(()->stream.parallel().foreach(doSomething)); 所以,我这样做了: 我创建了一组线程名,以查看创建了多少线程,并记录了池中活动线程的数量,这两个数字都不超过16,所以这意味着这里的并行度不超过16(为什么甚至是16?)。如果我不使用forkJoinPool,我得到4作为并行度

  • 到目前为止,我有这个: 和这个: 当我测试这个时,它不能采取双倍数字,我收到这个消息: 我该如何解决这个问题?

  • 问题内容: 我正进入(状态 : 当我尝试运行以下 (尽管不完整) 代码段时: 在如下所示: 我正在尝试和班级之间建立联系。 发生此异常的原因是什么? 我创建了两个表并使用以下sql命令: POJO 人 地址 问题答案: 对于多对多关系交换,您需要专用的映射表 6.2.4。价值和多对多关联的集合 即,您需要类似PersonAddress表的内容 其中p_id是对人员表的FK引用,而a_id是对地址表

  • 问题内容: 我正进入(状态 : 当我尝试运行以下 (尽管不完整) 代码段时: 在如下所示: 我正在尝试和班级之间建立联系。 发生此异常的原因是什么? 我创建了两个表并使用以下sql命令: POJO 人 地址 问题答案: 对于ManyToMany Relationshhip,您需要专用的映射表 6.2.4。价值和多对多关联的集合 即,您需要类似PersonAddress表的内容 其中p_id是对人员