В Java, как я могу поймать исключение, выброшенное из дочернего потока, а затем выбросить его снова из родительского потока - PullRequest
0 голосов
/ 17 мая 2018

В настоящее время у меня есть следующий пример кода, который я пытаюсь преобразовать в OutputStream в InputStream, идея которого пришла от Method 2 в http://blog.ostermiller.org/convert-java-outputstream-inputstream

Но мой вопрос здесь заключается в том, что метод save мог выдатьIOException, и я хотел бы поймать это и повторно выдать это как часть этого метода getInputStream.

Я пытаюсь обернуть IOException, выброшенное save (out), в исключение времени выполнения, но я знаю, что этоисключение времени выполнения не может быть перехвачено родительским потоком.Так что я застрял в этом, может кто-нибудь указать мне несколько направлений?

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

Я прочитал Как поймать исключение из потока , но чувствовал, что мой вопрос все еще другой, поскольку я хочу повторно выдать исключение в родительском потоке, приведенный выше вопрос решает проблему, которая перехватывает только исключение

Ответы [ 2 ]

0 голосов
/ 18 мая 2018

Но мой вопрос здесь заключается в том, что метод save может генерировать IOException, и я хотел бы отловить это и повторно выдать его как часть этого метода getInputStream.

Вы можете 'сделать это, потому что исключение может быть вызвано в фоновом потоке, выполняющем save() через много времени после возврата getInputStream().

Если save() может вызвать исключение по какой-то причине, отличной от IOException, из егоPipedOutputStream, и вы хотите передать некоторую информацию об этой ошибке потоку, который читает из PipedInputStream, отправка Callable в ExecutorService, вероятно, является правильным подходом.Примером этого случая может быть то, что save() запрашивает базу данных и записывает результаты в поток;Если запрос не выполнен, вы хотите записать SQLException в потоке, который читает этот поток. Поток чтения может прочитать PipedInputStream, а затем проверить Future, полученный при отправке задачи.на ExecutorService, чтобы увидеть, завершилось ли оно ненормально.

Но если вам не нужна информация из исключения, выданного save(), и вы просто хотите выбросить исключение в поток, читающий из соответствующегоPipedInputStream, просто дайте фоновому потоку умереть.Это вызовет «сломанную трубу» IOException в главном потоке, когда он попытается прочитать из PipedInputStream.

0 голосов
/ 17 мая 2018

Хотя все комментарии, которые приводят к необработанному обработчику исключений и тому подобному, являются правильными, я хотел бы опубликовать этот ответ в качестве альтернативы.

Вы можете использовать ExecutorService, который вернет вам Future, а затем выможет получить ExecutionException при получении результата, что-то вроде этого (набрав прямо здесь, может потребоваться некоторая проверка):

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