3

と を実行するスレッドのペアがSocketありServerSocketます。

runThreadA() {
     // Connects to B, or fails if B is not yet accepting
     socket.connect();
}

runThreadB() {
    // Blocks until another thread connects
    serverSocket.accept();
}

呼び出しの前にB呼び出しaccept()とブロックを保証できる方法はありますか?Aconnect()

4

3 に答える 3

1

CyclicBarrierCountDownLatchを確認すると、スレッドを相互に待機させることができます。役立つ場合があります。

于 2013-08-14T21:10:34.470 に答える
1

適切にコーディングします。connect() が失敗した場合は、問題をログに記録し、バックオフ タイムを待ってから再試行します。サーバーがリッスンしている場合でも、connect() が他の理由で失敗する可能性があります (たとえば、ネットワーク API のどこかのレイヤーでバッファーがいっぱいになっているなど)。これIOExceptionが制御された例外であり、Java コンパイラは明示的にそれを処理することを期待してIOExceptionいます。

private static final Logger LOG = Logger.getLogger(YourClass.class);

for (int waitTime = 10; waitTime < 10000; waitTime *= 2) {
    try {
        socket.connect();
    } catch (ConnectException ex) {
        LOG.log(Level.WARNING,
                "Connection failed, retrying in " + waitTime + " ms...", ex);
        Thread.sleep(waitTime);
    } catch (IOException ex) {
        throw new RuntimeException("Unexpected IO Exception", ex);
    }
}

バリアやシグナリングなど、いくつかの同期プリミティブを使用した場合でも、サーバー スレッドはlisten() が実際に有効になる前に常にシグナルを送信します。そのため、不正なスレッド インターリーブが発生する可能性は依然としてあります。

于 2013-08-14T22:33:35.730 に答える
-1

ええ、妥当なタイムアウトを設定してください

 runThreadA() {
    Socket s = new Socket()
    s.connect(endPoint, REASONABLE_TIMEOUT )
 }

そうすれば、スレッド A は接続を試みますが、あきらめる前に妥当な時間待機します。

アップデート

もう 1 つの方法は、2 番目のスレッドに同じ妥当な時間だけ再試行させることです。

runThreadA() {
    maxTimeout = currentTime() + REASONABLE_TIMEOUT
    while ( currentTime() < maxTimeout ) { 
       socket.connect()
       if ( isConnected( socket ) ) { 
           break;
       }
       Thread.currentThread.sleep( A_WHILE )
    }
    if ( ! isConnected( socket ) ) { 
        .... too bad, we can't work this way
        exit();
    } 
    continue with the work here...
} 
于 2013-08-14T20:27:15.240 に答える