Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/395.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 异常向主线程的传播_Java_Multithreading_Exception Handling_Future_Runnable - Fatal编程技术网

Java 异常向主线程的传播

Java 异常向主线程的传播,java,multithreading,exception-handling,future,runnable,Java,Multithreading,Exception Handling,Future,Runnable,在以下情况下,为什么两个异常都会传播到主线程 (这是一个测试,我已将其配置为在调用stop()时引发运行时异常): List futures=new ArrayList(); futures.add(executorService.submit(runnable1)); futures.add(executorService.submit(runnable2)); 线程。睡眠(1000L);//等待runnables运行一段时间 runnable2.stop(); runnable1.stop(

在以下情况下,为什么两个异常都会传播到主线程

(这是一个测试,我已将其配置为在调用stop()时引发运行时异常):

List futures=new ArrayList();
futures.add(executorService.submit(runnable1));
futures.add(executorService.submit(runnable2));
线程。睡眠(1000L);//等待runnables运行一段时间
runnable2.stop();
runnable1.stop();
for(未来:未来){
试一试{
future.get();
}捕获(例外e){
System.out.println(“发生异常”);
}
}
我希望只有第一个会被传播,因为第二个会被这个设置吞没(因为它通过按顺序循环遍历数组列表来等待第一个runnable)

如果我们只调用runnable2.stop(),就可以看到这种吞咽的例子——在这种情况下,根本没有显示任何内容

为什么会打印runnable2的例外


我还应该提到,当在每个线程上调用stop()时,方法内部会有一个暂停,然后抛出异常,以允许继续调用futures循环。

如果只在第二个线程上调用
stop()
,那么
for
循环将永远等待第一个线程完成。例外没有被吞没;它已被捕获,并且当您的程序在第二个将来调用
get()
时将抛出,但您的程序已挂起等待第一个将来,并且不会到达该点

在以下情况下,为什么两个异常都会传播到主线程

这就是
未来类的本质。它包装您的作业,因此无论执行和完成作业的顺序如何,当您调用
future.get()
时,它都将返回结果或引发异常

因此,如果第二个作业首先抛出异常,它将存储在与该作业相关联的
Future
中,以便在以后查看
futures
列表时可以返回异常,即使第一个
Future.get()
可能需要等待第一个作业完成

如果愿意,您可以查看
FutureTask
的代码。以下是一些片段:

public void run() {
  ...
            try {
                // Gray: this calls your job, storing the result
                result = c.call();
                ran = true;
            } catch (Throwable ex) {
                result = null;
                ran = false;
                // this puts ex into result and sets the state to EXCEPTIONAL
                setException(ex);
            }
然后:


因此,当运行完成
call()
方法的结果或产生的异常与
NORMAL
exception

状态一起存储在
output
中时,我不明白为什么在到达循环时第二个异常不会被清除,两项任务都已完成。那么你为什么期望一个被吞下呢?@MauricePerry,因为循环的性质,我们正在等待runnable1首先完成。如果使用此设置仅在第二个线程上调用stop,则不会显示任何内容。如果我对第一个线程执行相同的操作,我们会看到一个异常,它会在第二个线程上开始等待。但是在这里,您同时停止了这两个线程。所以这两个测试都已完成,所以不需要等待。@realponsign抱歉,我没有提到此测试配置为在完成之前调用stop()时在每个线程中暂停。测试一下,你会发现同样的行为。
public void run() {
  ...
            try {
                // Gray: this calls your job, storing the result
                result = c.call();
                ran = true;
            } catch (Throwable ex) {
                result = null;
                ran = false;
                // this puts ex into result and sets the state to EXCEPTIONAL
                setException(ex);
            }
public V get() throws InterruptedException, ExecutionException {
   ...

    Object x = outcome;
    if (s == NORMAL)
        return (V)x;
    if (s >= CANCELLED)
        throw new CancellationException();
    throw new ExecutionException((Throwable)x);