在不使用stop()方法的情况下结束Thread的执行

时间:2012-06-09 04:42:04

标签: java multithreading

我有一个带有按钮的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()并停止循环。

这里可以做些什么?

3 个答案:

答案 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()会使其挂起。