我有一个带有按钮的Swing表单,单击该按钮时会启动SocketServer
以在单独的线程中侦听传入的请求。以下是我所拥有的课程结构。
MainForm
:这是我发布Swing Form的主要类。它有两个按钮,“启动服务器”和“停止按钮”。MySocketServer
:此类是SocketServer
对象所在的位置,它包含方法startServer()
和stopServer()
。以下是“开始”按钮的“Click Event Body”。
t = new Thread(new Runnable() //Object t is created globally in this main class.
{
public void run()
{
myss = new MySocketServer(); //Object myss has similar accessibility as t.
myss.startServer();
}
});
t.start();
以下是停止按钮的Click Event Body
myss.stopServer();
if(t.isAlive());
System.out.println("Thread is still alive!!");
虽然我可以按照我想要的时间切换SockeServer“开始”和“停止”,但我意识到每次启动服务器时,都会创建新线程,即使使用MySocketServer
停止服务器,它也会保持活动状态的方法。
我可以使用stop()
的{{1}}并停止线程执行,但由于它已经过折旧,我已经研究过一旦Thread
方法完全执行后线程就会结束,但我有run()
方法分开,以便它可以单独处理连接的客户端。
请注意startServer()
具有While-Listen循环,因此基本上startServer()
线程的方法处于无限执行状态,直到我显式调用run()
并停止循环。
这里可以做些什么?
答案 0 :(得分:2)
首先,您不应尝试使用Thread.stop()
。这是有潜在危险的。
那你该怎么办?
一种可能性是编写服务器线程,如下所示:
....
ServerSocket ss = new ServerSocket(...);
try {
while (keepGoing) {
Socket s = ss.accept(...);
try {
// do stuff
} finally {
// close socket
}
}
} finally {
// close the server socket
}
并stopServer
清除keepGoing
标志。但问题是,当accept
调用中的线程被阻塞时,停止通常会出现,并且没有任何内容可以解除阻塞。
另一种可能性是在线程上调用Thread.interrupt()
。这导致一些东西被解除阻塞,并抛出一个异常,但我认为它不会解锁accept()
调用。 (但是,如果“do stuff”部分需要中断,这仍然比设置标志更好。)
真正的解决方案(我认为)是关闭ServerSocket
。这将导致ss.accept()
调用解除阻塞并抛出异常,您需要在服务器线程中处理该异常。
答案 1 :(得分:0)
在while循环的MySocketServer类中,你需要一个标志来测试它是否应该继续运行。
在新添加的关闭方法中,设置线程中的循环将测试的标志。一旦循环中断并且run()返回,线程将结束。
答案 2 :(得分:0)
你不应该使用stop()。看看这个http://docs.oracle.com/javase/1.4.2/docs/guide/misc/threadPrimitiveDeprecation.html 具有无限循环和启动/停止标志的解决方案很简单,但会导致CPU时间的无效使用。更好的方法是使用wait / notify方法。使用MySocketServer的方式让我觉得你在startServer()中有其他无限循环。这就是你必须阻止它的原因。最好将此循环内部包装到其自己的线程中,并使启动/停止方法以等待/通知方式使用此线程状态进行操作。 忘了提一下,因为你的GUI在自己的线程中运行,你无法在MySocketServer中转义启动/停止标志,因为在GUI线程中使用wait()会使其挂起。