如果要打开socket,如何中断线程?

时间:2012-03-13 19:34:06

标签: java multithreading interrupt

我试图关闭当前线程,它是多线程服务器的一部分。 该线程已准备好打开客户端可以访问的套接字。

除非下面的代码包含在while()循环中,否则一切正常。

  

new ServerThread(serversocket.accept(),this.Rstr,   bag.numberofDatatoAcquire)。开始();

以下是服务器的代码:

public void run() {

    System.out.println("This has been called ");   

    try{

       System.out.println("This has been tried");    
       serversocket = new ServerSocket(this.iPort);                                 

       Thread thisThread = Thread.currentThread();

       while(!thisThread.isInterrupted()){
           new ServerThread(serversocket.accept(), this.Rstr, bag.numberofDatatoAcquire).start();
           //sending socket accessed, where it will store the data and how much it will collect it.                            
           System.out.println("This has been running");                  
           Thread.sleep(10);               
       }           
    }catch(InterruptedException e){
        //why bother? it is an usual happening...lol
    }catch(IOException ioe)
    {
        System.err.println("Can't open the socket on port");               
    }
    finally{     
       System.out.println("Thread is dead and ready for change");
    }
}

这是GUI事件的一部分:如果没有“new ServerThread ...”代码,这种方法很有效。

private OverWatch EW = new OverWatch(bag.iPortOrder, bag.SessionAcquisitionSavingDirectory);   

....

private void OverWatcherControl(boolean checker)
{
    if(checker)
        EW.start();  
    else
        EW.interrupt();

}

由于变量bag.numberofDataToAcquire(公共整数类型)应该在用户需要时更改,我想我必须停止此线程并更改变量然后再次运行此线程。我错了吗?或者我该如何中断这个帖子?

谢谢,

3 个答案:

答案 0 :(得分:11)

ServerSocket.accept()是一个阻止调用,无法响应线程中断。几乎所有java.net阻塞调用(连接,读取,接受等)都不响应Thread.interrupt()。此行为是“按设计的”。

唤醒在.accept().read()中阻止的线程的一种方法是关闭底层套接字。

或者,您可以在ServerSocket上设置SO_TIMEOUT(setSoTimeout),这会导致.accept()通过抛出SocketTimeoutException来定期唤醒。您可以捕获该异常并将其用作检查线程上的中断状态的机会。

java.nio包(Java 1.4+)提供了一个备用套接字API,可以更好地响应中断。

答案 1 :(得分:6)

就像替代使用超时或杀死套接字一样:

伪造与套接字的新连接。这将“唤醒”accept(),然后可以使用额外的信令机制(例如标志或中断检查)(尽管逻辑必须从显示到{{1 }})。

我之前使用过这种方法并且运行良好:无需等待超时(甚至排序)或处理另一个异常,并且套接字保持打开/有效(可能需要也可能不需要)。另一方面,我不确定真的很长/破坏 TCP握手会发生什么,但这是我从未遇到的情况; - )

快乐的编码。

答案 2 :(得分:2)

我最初使用serverSocket.setSoTimeout(millis)回答了问题并处理了SocketTimeoutException。见下文。

更好的方法是使用ServerSocketChannel,当您拨打accept()时,thread.interrupt()会在ServerSocketChannel socketChannel = ServerSocketChannel.open(); socketChannel.socket().bind(new InetSocketAddress(this.iPort), 10); ... while (! thisThread.isInterrupted()) { // channel accepts _are_ interrupted by the call to thread.interrupt() // it throws ClosedByInterruptException when interrupt() is called SocketChannel accepted = socketChannel.accept(); new ServerThread(accepted.socket(), this.Rstr, bag.numberofDatatoAcquire).start(); } 来电中断,这样您根本不需要旋转。所以你会做类似的事情:

while(!thisThread.isInterrupted()){
   new ServerThread(serversocket.accept(), this.Rstr,
        bag.numberofDatatoAcquire).start();
   Thread.sleep(10);               
}           

我会解释一下代码:

serversocket.accept()

我认为您的问题是while 挂起等待接受套接字。来自accept() javadocs

  

侦听与此套接字的连接并接受它。该方法将阻塞,直到建立连接。

您需要在serversocket.setSoTimeout(10000); 循环之前在套接字上设置超时。您可以使用setSoTimeout(millis)

SocketTimeoutException

如果超时,则会抛出Thread.sleep(10)。那么你将不需要accept()(这是10ms btw),因为睡眠将在accept(10)方法内完成。我会推荐{{1}}因为那会非常积极地旋转。