我试图关闭当前线程,它是多线程服务器的一部分。 该线程已准备好打开客户端可以访问的套接字。
除非下面的代码包含在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(公共整数类型)应该在用户需要时更改,我想我必须停止此线程并更改变量然后再次运行此线程。我错了吗?或者我该如何中断这个帖子?
谢谢,
答案 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}}因为那会非常积极地旋转。