我编写了一个线程类,它通过每秒发送一个小字符串来检查与服务器的套接字连接。
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;
}
答案 0 :(得分:2)
我不知道为什么那不起作用,但它看起来有点混乱。您可能必须将Check
声明为volatile
,以确保循环始终读取当前值,以便新线程覆盖它时。
恕我直言,一个更好的方法是一个单独的“主管”线程,它负责启动其中一个线程,然后使用Thread.join()
等待它死掉,此时它可以再次启动它。
通过这种方式,你的主线程的逻辑可以专注于所谓的所做的事情,而不需要任何“自我意识”。
答案 1 :(得分: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;
}
}
}
答案 2 :(得分: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