我正在尝试为呼叫/响应ping建立超时。这是为了确定在自动连接序列中使用哪个CommPort。当我发送CALL_SIGNAL
字节[]时,我希望得到“FU”作为回复。这就是我将如何确定哪个是我的设备。 SSCCE在下面(对不起长度,但 缩短版本)
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.Timer;
import java.util.TimerTask;
import javax.comm.CommPortIdentifier;
import javax.comm.CommPort;
import javax.comm.PortInUseException;
import javax.comm.SerialPort;
public class PingTest {
public static final long PING_TIMEOUT = 1000; // in millis
public static final byte[] CALL_SIGNAL = {70, 68, 73, 68};
public boolean ping(CommPortIdentifier cpi) {
System.out.println("Pinging " + cpi.getName());
CommPort port = null;
InputStream input = null;
OutputStream output = null;
//Initialization test
try {
port = cpi.open("pingTest", 50);
input = port.getInputStream();
output = port.getOutputStream();
} catch (PortInUseException ex) {
if (cpi.getCurrentOwner().startsWith("pingTest")) {
System.out.println("Port already owned by this application.");
return true;
}
return false;
} catch (Exception ex) {
try {
port.close();
} catch (NullPointerException e) {
}
System.out.println("Failed initialization test.");
System.err.println(ex);
return false;
}
System.out.println("Passed initialization test.");
//Call and response test
final Stop stop = new Stop();
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("Stop timer triggered.");
stop.shouldStop = true;
}
}, PING_TIMEOUT);
try {
System.out.println("Writing...");
output.write(CALL_SIGNAL);
System.out.println("Reading...");
boolean waitForF = true;
while (!stop.shouldStop && !stop.didPass) {
if (waitForF) {
if ((byte) 'F' == input.read()) {
waitForF = false;
}
} else {
System.out.println('F');
if ((byte) 'U' == input.read()) {
System.out.println('U');
stop.didPass = true;
} else {
System.out.println();
waitForF = true;
}
}
}
} catch (IOException ex) {
System.out.println("Failed I/O test.");
return false;
} finally {
port.close();
}
if (stop.didPass) {
System.out.println("Successful ping.");
return true;
}
System.out.println("Failed call and response test.");
return false;
}
public static void main(String[] args) {
PingTest pinger = new PingTest();
Enumeration<CommPortIdentifier> ports = CommPortIdentifier.getPortIdentifiers();
boolean trigger = true;
String name = null;
while (trigger && ports.hasMoreElements) {
CommPortIdentifier cpi = ports.nextElement();
name = cpi.getName();
trigger = !ping(cpi);
}
if (trigger) {
System.out.println("Found it. It is " + name);
} else {
System.out.println("Not Found");
}
}
}
class Stop {
boolean shouldStop = false;
boolean didPass = false;
}
我的输出是:
Pinging COM1
Passed initialization test.
Writing...
Reading...
Stop timer triggered.
然后应用程序冻结。尝试使用Timer
停止while循环是否有问题?
答案 0 :(得分:1)
你的阅读是封锁的。您需要使用Timeouts
答案 1 :(得分:0)
您正在同时访问来自不同线程的共享状态(shouldStop
和didPass
变量)而没有任何同步。如果要确保读取其他线程所写的内容,则应同步每个访问。
因此,要么添加方法来获取和设置这些变量,并使这些方法同步,或者,如果每个变量代表另一个变量的不同信息,并且它们可以独立编写和读取,则使这些变量易变。
第三种方式(仅在与volatile解决方案相同的条件下有效)是使用AtomicBoolean变量而不是布尔变量。