在java中如何捕获从子线程抛出的异常然后从父线程

时间:2018-05-17 18:44:06

标签: java multithreading exception-handling io

我目前有以下示例代码,我试图将OutputStream转换为InputStream,我从http://blog.ostermiller.org/convert-java-outputstream-inputstream中的Method 2得到了这个想法

但我的问题是,save方法可能抛出IOException,我想抓住它并重新抛出它作为这个getInputStream方法的一部分。

我试图将save(out)抛出的IOException包装到运行时异常中,但我知道父线程无法捕获此运行时异常。所以我坚持这个,有人能指出一些指示吗?

public InputStream getInputStream() throws IOException {
    PipedInputStream in = new PipedInputStream();
    PipedOutputStream out = new PipedOutputStream(in);
    Thread t = new Thread(new Runnable() {
        public void run () {
            try {
                save(out); // this save method can throw IOException
            } catch (IOException e) {
                throw new RuntimeException("Failed to save entries to output stream", e);
            }
        }
    });
    t.start();

    return in;
}


private void save(OutputStream out) throws IOException {...}  

我看过How to catch an Exception from a thread,但觉得我的问题仍然不同, 因为我想在父线程中重新抛出异常,上面的问题解决了仅捕获异常的问题

2 个答案:

答案 0 :(得分:0)

虽然导致未捕获的异常处理程序和类似内容的所有注释都是正确的,但我想将此答案作为替代方法发布。

您可以使用ExecutorService来返回Future,然后在获取结果时可以捕获ExecutionException,类似这样(直接在这里输入,可能需要一些验证):

ExecutorService pool = Executors.newFixedThreadPool(1);
Future result = pool.submit(this::save);
result.get(); // will throw ExecutionException

答案 1 :(得分:0)

  

但我的问题是,save方法可能抛出IOException,我想抓住它并重新抛出它作为这个getInputStream方法的一部分。

您无法做到这一点,因为在save()返回很久之后执行getInputStream()的后台线程中可能会引发异常。

如果save()IOException以外的PipedOutputStream以外的其他原因而抛出异常,并且您希望将有关该失败的一些信息传达给正在读取的线程PipedInputStream,向Callable提交ExecutorService可能是正确的做法。这种情况的一个例子是save()查询数据库,并将结果写入流;如果查询失败,您希望在正在读取该流的线程中记录SQLException 阅读线程可以读取PipedInputStream,然后检查{{1}收到的是从Future提交任务以查看它是否异常完成。

但是,如果您不需要ExecutorService引发的异常中的任何信息,并且只想在从相应的save()读取的线程中抛出异常,只需让后台线程死。这会引起一根破裂的管道#34;主线程中的PipedInputStream在尝试从其IOException读取时。