0

次のシナリオがあります。

  • サーバーは ServerSocketChannel を開き、クライアント接続を受け入れます。
  • すべての接続 (socketA) は新しいスレッドで処理されます。
  • スレッド内で、別のサーバーに接続する新しい SocketChannel (socketB) を開きます。
  • この時点で、元のクライアント接続 (socketA) はアイドル状態です。
  • 新しい SocketChannel は、サーバーからデータを読み取ります (ブロック)。

今、私はスレッドを中断します。私は、socketB が中断されて閉じられ、socketA が引き続き機能することを期待していました。残念ながら、socketA も中断されます。

何が問題なのですか?

動作を再現するために、次のテスト方法を使用します。

private void testServerSocket() throws IOException, InterruptedException
{
    final InetSocketAddress     address         = new InetSocketAddress( "localhost", 12345 );
    final ServerSocketChannel   serverChannel   = ServerSocketChannel.open();
    serverChannel.socket().bind( address );

    final SocketChannel socketChannel   = serverChannel.accept();

    // start communication in new thread
    final Thread    thread  = new Thread( new Runnable() { @Override public void run() { testWrite( socketChannel ); } } );

    thread.start();

    // wait a little bit
    Thread.sleep( 5000 );

    // interrupt thread, will interrupt the socketChannel.read in testRead()
    thread.interrupt();
    thread.join();

    socketChannel.close();
    serverChannel.close();
}

void testWrite( SocketChannel socketA )
{
    try
    {
        // write to client
        socketA.write( ByteBuffer.wrap( "0123456789".getBytes() ) );

        // open new socket to another server
        testRead();

        // throws ClosedByInterruptException
        socketA.write( ByteBuffer.wrap( "0123456789".getBytes() ) );
    }
    catch( final IOException e )
    {
        e.printStackTrace();
    }
}

void testRead()
{
    try
    {
        final InetSocketAddress address   = new InetSocketAddress( "localhost", 12346 );
        final SocketChannel     socketB   = SocketChannel.open( address );

        // server doesn't send, so this call will block and interrupted 
        socketB.read( ByteBuffer.wrap( new byte[10] ) );

        socketB.close();
    }
    catch( final IOException e )
    {
        e.printStackTrace();
    }
}
4

1 に答える 1

1

inThread.interrupted()の後に呼び出して、スレッドの中断状態をクリアする必要があります。実際には、そこでキャッチして実行する必要があります。そうしないと、この状態が持続し、書き込みも中断されます。IOExceptiontestRead()ClosedByInterruptException

于 2012-12-17T12:13:47.877 に答える