My Java-program does a multithreaded XSLT Transformation and writes the resul开发者_JAVA百科ts to a file. To avoid the IO bottleneck I am experimenting with the new AsynchronousFileChannel. The XSLT-Threads should submit their output as strings (which works) and the Writer to append them to the file (that does not work yet).
I wrote a custom Writer-class for the write-operations. My Threads call the Writer.write(String text)-method. In there I would like to append the String as ByteBuffer to the AsynchronousFileChannel. Unfortunately, I could find no hint what to use as the position value in asyncOutput.write(ByteBuffer, Long). I tried different values for position without success (Output gets scrambled). I am pretty sure, there is no problem with synchronization as the code works well with FileChannels (which do not support a simple non blocking io mode):
- asyncOutput.size()
- asyncOutput.size() + future.get().longValue()
- 0
Here's the code how I am trying to do this:
public class MyWriter {
private AsynchronousFileChannel asyncOutput;
MyWriter(String filename) throws IOException {
asyncOutput = AsynchronousFileChannel.open(Paths.get(filename), StandardOpenOption.CREATE, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING);
}
public void write(String output) throws IOException, ExecutionException, InterruptedException {
System.err.println("Write was called");
this.future = asyncOutput.write(string2ByteBuffer(output), asyncOutput.size());
}
public ByteBuffer string2ByteBuffer (String text){
...
}
}
The method is called from a the XSLT-Threads (Runnable) like this:
synchronized (this) {
this.write2Writer(outputXmlWriter.toString());
}
...
private void write2Writer(String output) throws IOException {
try {
myWriter.write(output);
} catch (ExecutionException | InterruptedException ex) {
ex.printStackTrace();
}
}
I could find no hint what to use as the position value in asyncOutput.write(ByteBuffer, Long)
It is the position you want to position at. I don't see what's so mysterious about it.
AsynchronousFileChannel does not have a global position, this is deliberate. Instead this channel provides an asynchronous API for applications that need to access different parts of a file at the same time.
The solution extracted from the link:
Future<Integer> future = asyncOutput.write(string2ByteBuffer(output), this.position);
this.position += future.get();
Source: http://cr.openjdk.java.net/~alanb/6830721/webrev.00/test/java/nio/channels/AsynchronousFileChannel/Basic.java.html
精彩评论