3

我编写了一个线程类,它通过每秒发送一个小字符串来检查与服务器的套接字连接。

begin()方法执行线程。

连接丢失后,线程尝试再次连接。

我的问题是是否可以像我一样通过方法begin()内的线程重新运行(见下文)。run()

public void begin() {  
   Check = new Thread(this);
   Check.start();
}

@Override
public void run() {
   Thread thisThread = Thread.currentThread();
   while (Check==thisThread) {
      try {
         oos.writeObject("a");
         // oos.flush();

         synchronized (this) {
            while (pleaseWait) {
               try {
                  System.out.println("waiting");    
                  wait();
                  System.out.println("not waiting");      
               } 
               catch (Exception e) {
                  System.err.println("Thread is interrupted: "+e.getMessage());
               }
            }
         }
         sleep(1000);
         } catch (Exception ex) {
              v = new Visual("The connection is lost. The system will try to reconnect now.");
              this.end();
              try {
                 Server=ClientLogin.checkingServers(); //returns the reachable server string address
                 socket = new Socket(Server, ServerPort);
                 System.out.println("Connected: " + socket);
                 oos = new ObjectOutputStream(socket.getOutputStream());
                 begin();
                 v = new Visual("The system is reconnected.");
              }
              catch(UnknownHostException uhe){  
                 System.out.println("Host unknown: " + uhe.getMessage());
                 v = new Visual("The system has failed to reconnected.");
              }
              catch (IOException ioe) {
                 System.out.println("The system cannot connect to servers: " + ioe.getMessage());
                 v = new Visual("The system has failed to reconnected.");
              }
              catch (Exception e) {
                 System.out.println("The system has failed to reconnect: " + e.getMessage());
                 v = new Visual("The system has failed to reconnected.");
              }
          }
   }
}

public void end() {
   Check = null;
}
4

3 回答 3

2

我不知道为什么这不起作用,但它看起来有点乱。您可能必须声明Checkvolatile以确保循环始终读取当前值,因为新线程会覆盖它。

恕我直言,更好的方法是一个单独的“主管”线程,负责启动其中一个线程,然后用于Thread.join()等待它死亡,此时它可以再次启动它。

通过这种方式,您的主线程的逻辑可以专注于它应该做的事情,而无需任何“自我意识”。

于 2012-09-02T21:21:03.593 回答
1

首先,代码不是线程安全的。“检查”字段由一个线程写入,但由另一个线程读取,但不同步。不能保证新启动的线程会看到“Check”的更新值,即新线程在检查“Check==thisThread”时会获取旧线程的引用并做错事,

这个特殊问题可以通过使“检查”字段易失来解决。它确保在更新时,每个线程都会看到新值。

在 run() 方法中调用“begin()”并不是“错误的”。但是我不推荐它,因为您在这里有效地创建了递归调用。你很有可能会弄错并陷入无限循环。试试下面的简单设计。它使用while循环而不是递归。

package com.thinkinginobjects;

public class HeathChecker {

public void run() {
    while (true) {
        boolean success = checkHeath();
        if (!success) {
            //log and re-establish connection
        } else {
            Thread.sleep(1000);
        }
    }
}

private boolean checkHeath() {
    try {
        oos.writeObject("a");
        return true;
    } catch (Exception ex) {
        return false;
    }
}

}

于 2012-09-02T23:14:48.013 回答
0

没关系,但是为什么每次都需要启动一个线程?使用 Timer 和 TimerTask 不是更好吗?

http://docs.oracle.com/javase/6/docs/api/java/util/TimerTask.html

http://docs.oracle.com/javase/6/docs/api/java/util/Timer.html

于 2012-09-02T21:16:57.743 回答