Java: Are parallel reads and writes possible when locking a SocketChannel via Object (In | Out) putStreams?

I created an ObjectInputSteam and an ObjectOutputStream when locking the SocketChannel and trying to read and write at the same time. My code looks something like this:

 socketChannel = SocketChannel.open(destNode); objectOutputStream = new ObjectOutputStream(Channels.newOutputStream(socketChannel)); objectInputStream = new ObjectInputStream(Channels.newInputStream(socketChannel)); Thread replyThread = new Thread("SendRunnable-ReplyThread") { @Override public void run() { try { byte reply = objectInputStream.readByte();//(A) //..process reply } catch (Throwable e) { logger.warn("Problem reading receive reply.", e); } } }; replyThread.start(); objectOutputStream.writeObject(someObject);//(B) //..more writing 

The problem is that the records in row (B) are locked until the reading in row (A) has finished (blocks on the object returned by SelectableChannel#blockingLock() ). But the application logic requires that the reading does not end until all records have completed, so we have an effective deadlock.

SocketChannel javadocs say concurrent reads and writes are supported.

I had no such problem when I tried the correct Socket solution:

 Socket socket = new Socket(); socket.connect(destNode); final OutputStream outputStream = socket.getOutputStream(); objectOutputStream = new ObjectOutputStream(outputStream); objectInputStream = new ObjectInputStream(socket.getInputStream()); 

However, I cannot take advantage of the performance of FileChannel#transferTo(...)

+6
java sockets nio
source share
4 answers

This seems to be a bug in java.nio.channels.Channels (thanks Tom Hawtin, post it next time as an answer). A good description and workaround are described here (actually a duplicate of Tom's error):

I tested the workaround and it works.

+2
source share

The workaround in the error report worked for me. It is worth noting that only one of the input or output data needs to be wrapped for a workaround in order to work - therefore, if performance is especially important in one direction, then you can wrap it less important and make sure that the other gets all the optimizations available to it.

 public InputStream getInputStream() throws IOException { return Channels.newInputStream(new ReadableByteChannel() { public int read(ByteBuffer dst) throws IOException { return socketChannel.read(dst); } public void close() throws IOException { socketChannel.close(); } public boolean isOpen() { return socketChannel.isOpen(); } }); } public OutputStream getOutputStream() throws IOException { return Channels.newOutputStream(socketChannel); } 
+2
source share

If you want to use InputStream and OutputStream simultaneously with SocketChannel, looking at the source, it seems that you need to call SocketChannel.socket () and use streams from what behave slightly differently.

+1
source share

Interesting mistake! You say that you cannot use FileChannel # transferTo. How to wrap non-NIO socket I / O streams into channels using Channesl # newChannel before passing to FileChannel # transferTo?

0
source share

All Articles