我有一个带有两个线程的PipedWriter + PipedReader对。我想,在写入线程中捕获的异常将被包含在IOException中的PipedReader的下一个操作抛出。如果PipedReader本身有错误,则可以将写入线程异常添加到抑制的异常中。
问题是如果在写入线程中发生错误,我只能关闭编写器,这会导致读取器端的EOF正常。我希望读者线程知道作者方面的错误。但我希望我的代码的用户应该看到一个简单的Reader。所以我必须将该错误表示为IOException。
你知道任何开箱即用的#34;错误授权pipedwriter + reader"在那里实施?你会如何以线程安全的方式实现这样的事情?
答案 0 :(得分:1)
我创建了一个“ErrorDelegatingReaderDecorator”:
import java.io.IOException;
import java.io.Reader;
class ErrorDelegatingReaderDecorator extends Reader {
static final String ERROR_MESSAGE_WRITER_THREAD = "Error occoured on the other side of the pipe. See the cause!";
static final String ERROR_MESSAGE_READER_THREAD = "Error occoured on the this side of the pipe. See the cause!";
private Reader decorated;
private Throwable delegatedThrowable;
public ErrorDelegatingReaderDecorator(Reader decorated) {
super();
this.decorated = decorated;
}
@Override
public int read(char[] cbuf, int off, int len) throws IOException {
Throwable originalException = null;
int result = -1;
try {
result = decorated.read(cbuf, off, len);
}
catch( Throwable original ) {
originalException = original;
}
finally {
throwException(originalException);
}
return result;
}
@Override
public void close() throws IOException {
Throwable originalException = null;
try {
decorated.close();
}
catch( Throwable original ) {
originalException = original;
}
finally {
throwException(originalException);
}
}
private synchronized void throwException(Throwable originalException) throws IOException {
Throwable delegatedTemp = delegatedThrowable;
delegatedThrowable = null;
if ( originalException != null ) {
if ( delegatedTemp != null ) {
originalException.addSuppressed(delegatedTemp);
}
throw new IOException( ERROR_MESSAGE_READER_THREAD, originalException ) ;
}
else if ( delegatedTemp != null ) {
throw new IOException( ERROR_MESSAGE_WRITER_THREAD, delegatedTemp );
}
}
public synchronized void setDelegatedThrowable(Throwable delegatedThrowable) {
this.delegatedThrowable = delegatedThrowable;
}
}
然后我可以像这样使用它:
final PipedWriter pipedWriter = new PipedWriter();
PipedReader pipedReader = new PipedReader( pipedWriter, pipeBufferSize);
final ErrorDelegatingReaderDecorator errorDelegatingReader = new ErrorDelegatingReaderDecorator( pipedReader );
executorService.execute( new Runnable( ) {
@Override
public void run() {
try
{
//do something that writes into the writer and can throw an error
} catch (Exception e) {
errorDelegatingReader.setDelegatedThrowable(e);
LOGGER.error( "Error while processing excel file.", e );
}
finally {
try {
pipedWriter.close();
} catch (IOException e) {
LOGGER.error( "Error while closing printwriter.", e );
}
}
}
});
//Giving out the decorated reader to the reader thread.
因为我必须从装饰读者的方法的finally部分抛出异常,所以我必须抓住Throwable
,我必须将其包装到IOException
中。它有点难看,但它不太可能发生在装饰PipedReader
上。
同样有趣的是我也告诉我,我是如何在发送EOF而不是抛出错误时出现间歇性失败:我在编写器块中使用了try-with-resources。这导致我的作家先被关闭,然后我在装饰器中设置了错误。如果两者之间我有一个阅读,那么它已成为一个EOF。所以我用普通的旧版块替换了它,现在订单没问题了。