2012-06-09 23 views
0

我有一个带有按钮的Swing窗体,点击该窗体时会开始SocketServer,用于侦听单独线程中的传入请求。以下是我拥有的课程结构。不使用stop()方法结束线程执行

  • MainForm:这是我的主要类,它启动Swing窗体。它有两个按钮,“启动服务器”和“停止按钮”。
  • 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事件车身

myss.stopServer(); 
if(t.isAlive()); 
    System.out.println("Thread is still alive!!"); 

虽然我可以切换SockeServer“开始”和“停止”作为我的时候,我想,但我知道,每次我开始服务器,新线程被创建,并且即使使用MySocketServer的方法停止服务器,它仍然保持活动状态。

我可以使用的Threadstop()和停止线程执行,但因为它是贬值,我研究过,一旦他们的run()方法已经完全执行的线程都结束了,但我已经startServer()法分离,以便它可以单独处理连接的客户端。

请注意startServer()有While-Listen循环,所以基本上run()线程的方法处于无限的执行状态,直到我明确地调用stopServer()并暂停循环。

这里可以做些什么?

回答

0

在你的MySocketServer类的while循环中,你需要一个标志来测试它是否应该继续运行。

在新添加的关闭方法中,设置线程中循环将测试的标志。一旦循环中断并且run()返回,线程将结束。

+0

我这是在'serverStart使用()'方法,它是在每次循环检查布尔标志,和我在'startserver的设置该标志为假()',而现在调试我才知道,虽然循环结束时调用'stopServer()',甚至'的run()'线程的方法典雅执行完毕,但为什么我收到'的IsAlive()'真的,即使运行完成? – Kushal

0

您不应该使用stop()。看看这个http://docs.oracle.com/javase/1.4.2/docs/guide/misc/threadPrimitiveDeprecation.html 带有无限循环和启动/停止标志的解决方案很简单,但会导致无法有效使用CPU时间。更好的方法是使用等待/通知方法。你用MySocketServer操作的方式让我感觉你在startServer()里面有其他的无限循环。这就是为什么你必须阻止它。将这个循环封装到它自己的线程中会更好一些,并且启动/停止方法以等待/通知的方式在这个线程状态下运行。 忘了提及,因为你的GUI运行在它自己的线程中,你不能逃脱MySocketServer里面的启动/停止标志,因为在GUI线程中使用wait()会导致它挂起。

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 
    } 

,并有明确stopServerkeepGoing标志。但问题是通常会在accept呼叫中线程被阻止时停止,并且没有任何东西可以解锁它。

另一种可能是在线程上调用Thread.interrupt()。这会导致一些事情被解除封锁,并引发异常,但我认为它不会阻止accept()调用。 (但是,如果“do stuff”部分需要中断,这仍然比设置标志更好)。

真正的解决方案(我认为)是关闭ServerSocket。这将导致ss.accept()调用解除阻塞并抛出一个异常,您需要在服务器线程中处理异常。

+0

如你所说关闭'ServerSocket',我已经在主类的我'stopServer()'方法进行这两项,关闭ServerSocket的,且布尔标志设置为false,这将最终结束循环。所以我相信'的run()'方法实际上是结束它的执行,但是我还是'的IsAlive()'真正的线程。 – Kushal

+0

在上面的代码中设置while条件为:! ss.isClosed()然后,如果你只需要调用无论从任何方法是关闭服务器ss.close(),accept方法将疏通和引发SocketException,你应该能够安全地捕获和忽略通过检查SS .isClosed()标志在你的catch块中。 – Matt