简体   繁体   中英

In java how can I catch an exception thrown from child thread and then throw it again from the parent thread

I currently have the following sample code that I am trying to convert OutputStream to InputStream, which I got the idea from Method 2 in http://blog.ostermiller.org/convert-java-outputstream-inputstream

But my question here is, the save method could throw IOException, and I would like to catch that and re-throw that as part of this getInputStream method.

I am trying to wrap the IOException thrown by save(out) to a runtime exception, but I know that this runtime exception cannot be caught by the parent thread. So I am stuck on this, can anyone point me some directions?

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 {...}  

I have read How to catch an Exception from a thread but felt my question is still different, because I want to re-throw the exception in parent thread, the question above solves the problem that catches the exception only

While all the comments that lead to uncaught exception handler and similar stuff are correct, I would like to post this answer as an alternative.

You can use an ExecutorService which will return you a Future and then you can catch ExecutionException when getting the result, something like this (typing directly here, might need some validation):

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

But my question here is, the save method could throw IOException, and I would like to catch that and re-throw that as part of this getInputStream method.

You can't do that, because an exception can be raised in the background thread executing save() long after getInputStream() returns.

If save() can throw an exception for some reason other than an IOException from its PipedOutputStream , and you want to convey some information about that failure to the thread that is reading from the PipedInputStream , submitting a Callable to an ExecutorService is probably the right approach. An example of this case would be that save() queries a database, and writes the results to a stream; if query fails, you want to log that SQLException in the thread that is reading that stream. The reading thread could read the PipedInputStream , and then check the Future it received from submitting the task to the ExecutorService to see if it completed abnormally.

But if you don't need any information from the exception thrown by save() , and just want to throw an exception in the thread reading from the corresponding PipedInputStream , simply let the background thread die. This will raise a "broken pipe" IOException in the main thread when it attempts to read from its PipedInputStream .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM