我刚刚发现下面的代码不像预期的那样工作。
try (AsynchronousFileChannel channel = open(path)) {
channel.read(, , ,
new CompletionHandler() {
@Override
public void completed(Integer result, Long attachment) {
}
@Override
public void failed(Throwable exc, Long attachment) {
// channel already has been closed!!!
}
});
}因为AsynchronousFileChannel#read方法立即返回,而CompletionHandler无法工作。
在任务完成后,关闭通道的常用习语是什么?
我应该这么做吗?
AsynchronousFileChannel channel = open(path);
channel.read(, , ,
new CompletionHandler() {
@Override
public void completed(Integer result, Long attachment) {
}
@Override
public void failed(Throwable exc, Long attachment) {
}
});
channel.close();发布于 2022-01-29 16:15:20
希望有人知道一个正确的方法来确保所有正在进行的AsynchronousFileChannel回调都完成了--我找不到一个合适的API调用来结束带回调的读操作。在测试中,我注意到在我的方法调用将数据读入其调用方之后,可能会调用CompletionHandler回调,这是在离开关闭AsynchronousFileChannel的try with资源块之后进行的。
try (AsynchronousFileChannel fc = AsynchronousFileChannel.open(p, StandardOpenOption.READ)) {
var handler = new CompletionHandler<Integer,Long>() {
public void completed(Integer result, Long position) {
// ...
}
public void failed(Throwable exc, Long position) {
// ...
}
};
// Run some reads:
fc.read(aByteBuffer, startPos, Long.valueOf(startPos), handler);
}
return blah;
// "handler" still can receive callbacks after this point!相反,我在方法中使用了一个使用CountDownLatch的解决方案,这样直到所有的fc.read调用都与对应的CompletionHandler completed / failed回调匹配后,才会退出try-catch块。
try (AsynchronousFileChannel fc = AsynchronousFileChannel.open(p, StandardOpenOption.READ)) {
// Work out how many fc.read calls you plan to do
int numberOfReads = 1;
CountDownLatch countdown = new CountDownLatch(numberOfReads);
var handler = new CompletionHandler<Integer,Long>() {
public void completed(Integer result, Long position) {
// ...
countdown.countDown();
}
public void failed(Throwable exc, Long position) {
// ...
countdown.countDown();
}
};
// Kick off numberOfReads x fc.read
fc.read(yourByteBuffer, startPos, Long.valueOf(startPos), handler);
// Without next line the AsynchronousFileChannel may continue to run after return
countdown.await();
}
return blah;
// No more "handler" callbacks after this point这不是一个理想的解决方案,因为它依赖于在创建CountDownLatch之前计算读取数。相反,您可以考虑使用动态计数器,或者使用非回调读取方法:Future<Integer> fut = read(ByteBuffer, long)样式,并在调用线程中调用fut.get();。
https://stackoverflow.com/questions/70903602
复制相似问题