我在与设备进行串行通信时使用java线程。它在调试模式下运行良好绝对完美,但是当我运行程序时,线程不执行指令。使用RXTX库进行串行通信,我的程序的其余部分在JavaFX(应用程序)中。
这是用于串行通信的类(SerialClass.java):
import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;
import gnu.io.SerialPortEvent;
import gnu.io.SerialPortEventListener;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.Enumeration;
public class SerialClass implements SerialPortEventListener {
public SerialPort serialPort;
/**
* The port we're normally going to use.
*/
private static final String PORT_NAMES[] = {
"/dev/tty.usbserial-A9007UX1", // Mac OS
"/dev/ttyACM0", // Linux
"COM21", // Windows
};
public static BufferedReader input;
public static OutputStream output;
/**
* Milliseconds to block while waiting for port open
*/
public static final int TIME_OUT = 2000;
/**
* Default bits per second for COM port.
*/
public static final int DATA_RATE = 9600;
public void initialize() {
CommPortIdentifier portId = null;
Enumeration portEnum = CommPortIdentifier.getPortIdentifiers();
//First, Find an instance of serial port as set in PORT_NAMES.
while (portEnum.hasMoreElements()) {
CommPortIdentifier currPortId = (CommPortIdentifier) portEnum.nextElement();
for (String portName : PORT_NAMES) {
if (currPortId.getName().equals(portName)) {
portId = currPortId;
break;
}
}
}
if (portId == null) {
System.out.println("Could not find COM port.");
return;
}
try {
// open serial port, and use class name for the appName.
serialPort = (SerialPort) portId.open(this.getClass().getName(), TIME_OUT);
// set port parameters
serialPort.setSerialPortParams(DATA_RATE,
SerialPort.DATABITS_8,
SerialPort.STOPBITS_1,
SerialPort.PARITY_NONE);
// open the streams
input = new BufferedReader(new InputStreamReader(serialPort.getInputStream()));
output = serialPort.getOutputStream();
char ch = 1;
output.write(ch);
// add event listeners
serialPort.addEventListener(this);
serialPort.notifyOnDataAvailable(true);
} catch (Exception e) {
System.err.println(e.toString());
}
}
public synchronized void close() {
if (serialPort != null) {
serialPort.removeEventListener();
serialPort.close();
}
}
public synchronized void serialEvent(SerialPortEvent oEvent) {
if (oEvent.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
try {
String inputLine = input.readLine();
System.out.println(inputLine);
} catch (Exception e) {
System.err.println(e.toString());
}
}
}
public static synchronized void writeData(String data) {
System.out.println("Sent: " + data);
try {
output.write(data.getBytes());
} catch (Exception e) {
System.out.println("could not write to port");
}
}
}
使用另一个类ImageInterface,它使用这个类:
import java.io.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.sanselan.ImageReadException;
import finImage.FinImage;
import img.ImageAccessor;
import img.ImageBean;
public class ImageInterface {
String image;
public static BufferedReader input;
public static OutputStream output;
public static synchronized void writeData(String data) {
System.out.println("Sent: " + data);
try {
output.write(data.getBytes());
} catch (Exception e) {
System.out.println("could not write to port");
}
}
public void openWithImage(File ImgFile) {
try {
// TODO code application logic here
ImageAccessor sa = new ImageAccessor();
ImageBean s = new ImageBean();
String ImgId = FinImage.getImageFromFin(ImgFile);
System.out.print(ImgId);
String sm = ImgId.toString();
System.out.print(sm);
String imageid = FinImage.getImageFromFin(ImgFile);
String sme;
Boolean flag = false;
if (imageid.startsWith("'")) {
sme = imageid.substring(1, imageid.length() - 1);
} else {
sme = imageid;
}
s = sa.getAllImageInfoById(sme);
System.out.print(s);
image = s.getFinPin();
//System.out.print(FinPin);
//System.out.print(FinPin);S
// image = ImgPin.toString();
System.out.print(image);
try {
SerialClass obj = new SerialClass();
int c = 0;
obj.initialize();
input = SerialClass.input;
output = SerialClass.output;
InputStreamReader Ir = new InputStreamReader(System.in);
BufferedReader Br = new BufferedReader(Ir);
Thread t = new Thread() {
public void run() {
obj.writeData(image);
}
//catch (InterruptedException ie){}
};
t.start();
System.out.println("Started");
obj.close();
} catch (Exception e) {
}
} catch (ImageReadException ex) {
Logger.getLogger(ImageInterface.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(ImageInterface.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
在上面的代码中,我正在访问Image中的id,然后通过串行通信写入它。在上面的程序中,线程在程序运行时不会写入,但在程序调试时会写入串行端口。我无法找出发生此类问题的确切原因。
使用Arduino输出。此外,我一直在使用2个操作系统,Ubuntu 12.04LTS和Windows 7.在Windows 7中,线程在调试中执行,而在Ubuntu 12.04中,线程在启动时不启动run方法。
请指出哪里出错了。
答案 0 :(得分:0)
您在“主”线程和“写入”线程之间创建了竞争条件。在启动写入线程后,您“主”调用线程close
。因为你不等待写线程完成,你可能在写任何东西之前关闭通道。事情往往在“调试”模式下运行较慢,因此在主线程调用close之前,写线程可能有时间完成。
一个简单的解决方案是在t.join()
调用之前添加obj.close()
。这将强制主线程等待写线程完成。但是,在您当前的代码中,不清楚为什么您正在使用第二个线程进行编写。