ServerSocket在accept()上阻塞时通知另一个线程

时间:2013-08-14 20:19:11

标签: java sockets concurrency

我有一对运行SocketServerSocket的线程:

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

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

有没有办法可以保证B拨打accept()并在A来电connect()之前屏蔽?

3 个答案:

答案 0 :(得分:1)

检查CyclicBarrierCountDownLatch这可以帮助您让线程互相等待,它们可能会有所帮助。

答案 1 :(得分: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()实际生效之前发出信号。因此,仍然存在错误的线程交错的可能性。

答案 2 :(得分:-1)

是的,设置合理的超时

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

这样,线程A将尝试连接,但它会在放弃之前等待一段合理的时间。

更新

另一种方法是让第二个线程重新尝试相同数量的REASONABLE时间。

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...
}