9

ブロッキングでObjectInputSteamandを作成し、同時に読み書きしようとしています。私のコードは次のようなものです:ObjectOutputStreamSocketChannel

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

問題は、行 (A) での読み取りが完了するまで、行 (B) での書き込みがブロックされることです (によって返されるオブジェクトのブロックSelectableChannel#blockingLock())。しかし、アプリのロジックは、すべての書き込みが完了するまで読み取りが完了しないように指示するため、実質的なデッドロックが発生します。

SocketChanneljavadocs によると、同時読み取りと書き込みがサポートされています。

通常の Socket ソリューションを試したとき、そのような問題は発生しませんでした。

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

ただし、パフォーマンス上の利点を利用することはできませんFileChannel#transferTo(...)

4

4 に答える 4

5

これはバグのようですjava.nio.channels.Channels(Tom Hawtin に感謝します。次回回答として投稿してください)。適切な説明と回避策がここに記載されています(実際には、Tom がリストしたバグの複製です):

回避策をテストしましたが、動作します。

于 2008-10-07T15:41:00.267 に答える
2

InputStream と OutputStream を SocketChannel と同時に使用する場合は、ソースを見ると、SocketChannel.socket() を呼び出して、動作がわずかに異なるストリームを使用する必要があるようです。

于 2008-10-06T16:23:53.677 に答える
0

面白いバグ!ただし、FileChannel#transferTo は使用できないと言っています。FileChannel#transferTo に渡す前に、Channelsl#newChannel を使用して非 NIO ソケットの I/O ストリームをチャネルにラップするのはどうですか?

于 2008-10-07T18:43:11.070 に答える