web-dev-qa-db-ja.com

ソケットのスレッドブロッキングを終了する方法IO操作を即座に?

Javaのコンテキストでは、GUIウィンドウを開くときにネットワーク入力を読み取る新しいスレッドを作成します。ウィンドウを閉じると、ソケットリソースを解放し、すぐにスレッドを終了します。今、私はsetSoTimeoutメソッドを使用していますが、タイムアウト例外を待ちたくありません。誰か提案をしてもらえますか?ありがとう!

65
Dingxin Xu

これを行うには(潜在的に)3つの方法があります。

  • ソケットで Socket.close() を呼び出すと、関連付けられたInputStreamおよびOutputStreamオブジェクトが閉じられ、Socketまたは(関連付けられた)ストリーム操作でブロックされたスレッドが発生します。ブロック解除されます。 javadocによると、ソケット自体の操作は SocketException をスローします。

  • Thread.interrupt() を呼び出すと、(指定されていない特定の状況下で)ブロッキングI/O操作が中断され、 InterruptedIOException がスローされます。 =。

    警告に注意してください。どうやら「interrupt()」アプローチは「ほとんどの」最新のJavaプラットフォームでは機能しません。(誰か他の人が時間と傾向がある場合、彼らはこのアプローチが機能する状況を調査することができますただし、動作がプラットフォーム固有であるという単なる事実は、アプリケーションが特定のプラットフォームでのみ動作する必要がある場合にのみ使用する必要があると言うのに十分なはずです。その時点で、自分で簡単に「試す」ことができます。

  • これを行う3つ目の方法は、 Socket.shutdownInput() および/または Socket.shutdownOutput() を呼び出すことです。 javadocsは、現在ブロックされている読み取りおよび/または書き込み操作で何が起こるかを明示的に述べていませんが、ブロックを解除して例外をスローすると考えるのは無理ではありません。ただし、javadocが何が起こるかを言わない場合、動作はプラットフォーム固有であると想定する必要があります。

55
Stephen C

私はこの質問が古いことを知っていますが、「現代のプラットフォーム」上のThread.interrupt()の「謎」を誰も解決していないようですので、私はいくつかの研究をしました。

これは、Java 8でテストされます(ただし、他のプラットフォームでも同様です)。

Thread.interrupt()を呼び出すとnotInterruptedIOExceptionをスローしますInputStream.read()メソッドが_-1_とThread.interrupted()- flagが設定されます。

したがって、以下はInterruptedIOExceptionをスローする「修正された」read()と見なすことができます。

_static final int read(Socket socket, byte[] inData) 
    throws SocketTimeoutException, // if setSoTimeout() was set and read timed out
           InterruptedIOException, // if thread interrupted
           IOException             // other erors
{
    InputStream in = socket.getInputStream();

    int readBytes = in.read( inData, 0, inData.length);

    if  ( Thread.interrupted() )
    {
        throw new InterruptedIOException( "Thread interrupted during socket read");
    }

    return readBytes;
}
_
16
raudi