I have some code where I send a ton of write operations to a file, mostly in fire-and-forget mode. Occasionally, I want to flush changes to disk just to give the user some confidence that if the power fails, they won't lose everything. To this end, I occasionally do this:
channel.write(ByteBuffer.wrap(new byte[0]), 0, null, new CompletionHandler<Integer, Object>() {
@Override
public void completed(Integer result, Object attachment) {
try {
channel.force(false);
}
catch (Throwable t) {
t.printStackTrace();
}
}
@Override
public void failed(Throwable exc, Object attachment) {
try {
channel.force(false);
}
catch (Throwable t) {
t.printStackTrace();
}
}
});
This does seem to cause the changes to be reflected on the disk, and it does not block the calling thread. Of course, it does block one of the threads in the channel's thread pool, thus preventing other writes from completing for a time.
It also has the disadvantage that CompletionHandler
's methods cannot throw exceptions, hence the catch-call catch blocks. For my application, absolute certainty that the force
has completed is not required, so this is not a problem.