----------------------- 重点在这里 -------------------------
这里有两个方法:1,是监听一个事务,需要长时间一次监听,大概一小时,所以if里面是判断时间的。
2,是每一秒钟都需要监听。而现在的情况是,每一秒钟都要判断一次 1 方法,效率很低,
所以要做成线程分离,做两个子类,test1,test2继承这个类,把这个run()给注释掉,写个空的,
我的思路是:在2方法中加个循环控制,循环3600次,就是一小时,然后放弃监听,把监听给1方法,
1方法走一次,然后放弃监听,给2方法。
现在的问题是:我找不到把监听对象替换的办法,serialPort.removeEventListener()好像是关闭监听,而不是消除对象!public class PortOperate implements Runnable, SerialPortEventListener {
private static Log log = LogFactory.getLog(PortOperate.class);
boolean bPortOpen = false; /* 来判断端口是否成功打开 */
private StringBuffer returnContent; /* 确定返回值 */
private CommPortIdentifier portId; /**/
private Enumeration portList; /* 存放所有COM */
private InputStream inputStream;
private OutputStream outputStream;
protected SerialPort serialPort; /**/
private byte[] last;
private SerialPort comm;
private boolean commandFlag;
Thread readThread;
long startTime = 0; //上次发送“读取阅读器id”指令时间
long readMachineInterval = 1000 * 60;//每隔多长时间发送一次“读取阅读器id”指令
private CommandResponseParser commandResponseParser = new CommandResponseParser();
List machineList = new ArrayList();
CommandProducer producer;
public PortOperate() {}
//这个方法用于查看是否有符合条件的串口。@return 如果找到匹配COM口,则返回true,否则false;
public boolean searchPort() {
portList = CommPortIdentifier.getPortIdentifiers();
while (portList.hasMoreElements()) {
portId = (CommPortIdentifier) portList.nextElement();
if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) {
System.out.println("找到串口:" + portId.getName()+" --- "+this.toString());
if (portId.getName().equals(FarpConst.ComName)) {
if(!bPortOpen){
try {
openPort();
System.out.println("bPortOpen is execute "+bPortOpen);
} catch (NoSuchPortException e) {
System.out.println("出现错误");
}
}
return true;
}// end of if...
}// end of if...
}// end of while...
return false;
}
// 这个方法用于打开接口,添加监听等。
void openPort() throws NoSuchPortException {
try {
serialPort = (SerialPort) CommPortIdentifier.getPortIdentifier(
FarpConst.ComName).open(getClass().getName(), 2000);// 2000为超时时间
System.out.println("openPort() is execute");
try {
serialPort.addEventListener(this);// 添加监听
System.out.println("openPort() is execute "+((String)this.toString()));
bPortOpen = true;
} catch (TooManyListenersException e1) {
this.closePort();
e1.printStackTrace();
}
// 设置接口有数据的事件true有效,false无效
serialPort.notifyOnDataAvailable(true);
// 设置中断事件true有效,false无效
serialPort.notifyOnBreakInterrupt(true);
try {
serialPort.setSerialPortParams(FarpConst.baudRate,
SerialPort.DATABITS_8, SerialPort.STOPBITS_1,
SerialPort.PARITY_NONE);// 奇偶位
} catch (UnsupportedCommOperationException e1) {
this.closePort();
e1.printStackTrace();
}
try {
outputStream = serialPort.getOutputStream();
inputStream = serialPort.getInputStream();
} catch (IOException ex) {
this.closePort();
ex.printStackTrace();
}
try {
serialPort.enableReceiveTimeout(1000);
} catch (Exception e) {
this.closePort();
System.out.println(e.getMessage());
}
} catch (Exception e1) {
//JOptionPane.showMessageDialog(null, "COM已经占用!");
}
}
public void closePort() {
try {
if (inputStream != null) {
inputStream.close();
}
if (outputStream != null) {
outputStream.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
if (serialPort != null) {
serialPort.close();
}
bPortOpen = false;
System.out.println("closePort() is execute ");
}
private OutputStream getOutputStream() {
if (serialPort == null) {
try {
openPort();
} catch (Exception e) {
log.error("", e);
return null;
}
}
try {
return serialPort.getOutputStream();
} catch (IOException e) {
throw new CommException("COMERR-005", e);
}
}
//发送RFIP命令
public synchronized void sendCommand(Command command) {
byte msg[];
if (command == null)
return;
msg = (byte[]) command.getBody();
if (log.isDebugEnabled())
log.info((new StringBuilder("Send command: ")).append(
ByteUtil.toHex(msg)).toString());
last = null;
commandFlag = true;
try {
if(serialPort.getOutputStream()==null){
commandFlag=false;
return;
}
} catch (Exception e) {
return;
}
try {
getOutputStream().write(msg);
getOutputStream().flush();
commandResponseParser.setCommand(command);
long begin = System.currentTimeMillis();
boolean timeout = false;
while (commandFlag) {
if (System.currentTimeMillis() - begin >= command.waitTime()) {
timeout = true;
break;
}
try {
Thread.sleep(1000L);
} catch (InterruptedException interruptedexception) {
}
}
if (log.isDebugEnabled())
log.debug((new StringBuilder("timeout: ")).append(timeout)
.toString());
if (timeout) {
startTime = 0;
}
if (log.isDebugEnabled())
log.debug("consume response");
command.consume();
} catch (IOException e) {
throw new CommException("COMERR-005", e);
}
commandFlag = false;
return;
}
// 解析指令执行后响应字符
public void consume(Machine machine, Object response) {
byte res[] = (byte[]) response;
HashSet cards = new HashSet();
if (res[3] == 85) {
int number = (0xff & res[2] - 3) / 2;
for (int i = 0; i < number; i++) {
byte b = res[4 + i * 2];
byte c = res[5 + i * 2];
int ci = 0x10000 + ((0x7f & b) << 8) + (0xff & c);
String cardId = Integer.toHexString(ci).toUpperCase()
.substring(1);
if (!cards.contains(cardId)) {
cards.add(cardId);
log.info("==machineid====:::::::"+res[1]+"===cardId===::::::"+cardId);
MachineService ms;
com.farp.bean.Machine ma=new com.farp.bean.Machine();
/*持久化到数据库中*/
}
}
}
}
这里有两个方法:1,是监听一个事务,需要长时间一次监听,大概一小时,所以if里面是判断时间的。
2,是每一秒钟都需要监听。而现在的情况是,每一秒钟都要判断一次 1 方法,效率很低,
所以要做成线程分离,做两个子类,test1,test2继承这个类,把这个run()给注释掉,写个空的,
我的思路是:在2方法中加个循环控制,循环3600次,就是一小时,然后放弃监听,把监听给1方法,
1方法走一次,然后放弃监听,给2方法。
现在的问题是:我找不到把监听对象替换的办法,serialPort.removeEventListener()好像是关闭监听,而不是消除对象!public class PortOperate implements Runnable, SerialPortEventListener {
private static Log log = LogFactory.getLog(PortOperate.class);
boolean bPortOpen = false; /* 来判断端口是否成功打开 */
private StringBuffer returnContent; /* 确定返回值 */
private CommPortIdentifier portId; /**/
private Enumeration portList; /* 存放所有COM */
private InputStream inputStream;
private OutputStream outputStream;
protected SerialPort serialPort; /**/
private byte[] last;
private SerialPort comm;
private boolean commandFlag;
Thread readThread;
long startTime = 0; //上次发送“读取阅读器id”指令时间
long readMachineInterval = 1000 * 60;//每隔多长时间发送一次“读取阅读器id”指令
private CommandResponseParser commandResponseParser = new CommandResponseParser();
List machineList = new ArrayList();
CommandProducer producer;
public PortOperate() {}
//这个方法用于查看是否有符合条件的串口。@return 如果找到匹配COM口,则返回true,否则false;
public boolean searchPort() {
portList = CommPortIdentifier.getPortIdentifiers();
while (portList.hasMoreElements()) {
portId = (CommPortIdentifier) portList.nextElement();
if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) {
System.out.println("找到串口:" + portId.getName()+" --- "+this.toString());
if (portId.getName().equals(FarpConst.ComName)) {
if(!bPortOpen){
try {
openPort();
System.out.println("bPortOpen is execute "+bPortOpen);
} catch (NoSuchPortException e) {
System.out.println("出现错误");
}
}
return true;
}// end of if...
}// end of if...
}// end of while...
return false;
}
// 这个方法用于打开接口,添加监听等。
void openPort() throws NoSuchPortException {
try {
serialPort = (SerialPort) CommPortIdentifier.getPortIdentifier(
FarpConst.ComName).open(getClass().getName(), 2000);// 2000为超时时间
System.out.println("openPort() is execute");
try {
serialPort.addEventListener(this);// 添加监听
System.out.println("openPort() is execute "+((String)this.toString()));
bPortOpen = true;
} catch (TooManyListenersException e1) {
this.closePort();
e1.printStackTrace();
}
// 设置接口有数据的事件true有效,false无效
serialPort.notifyOnDataAvailable(true);
// 设置中断事件true有效,false无效
serialPort.notifyOnBreakInterrupt(true);
try {
serialPort.setSerialPortParams(FarpConst.baudRate,
SerialPort.DATABITS_8, SerialPort.STOPBITS_1,
SerialPort.PARITY_NONE);// 奇偶位
} catch (UnsupportedCommOperationException e1) {
this.closePort();
e1.printStackTrace();
}
try {
outputStream = serialPort.getOutputStream();
inputStream = serialPort.getInputStream();
} catch (IOException ex) {
this.closePort();
ex.printStackTrace();
}
try {
serialPort.enableReceiveTimeout(1000);
} catch (Exception e) {
this.closePort();
System.out.println(e.getMessage());
}
} catch (Exception e1) {
//JOptionPane.showMessageDialog(null, "COM已经占用!");
}
}
public void closePort() {
try {
if (inputStream != null) {
inputStream.close();
}
if (outputStream != null) {
outputStream.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
if (serialPort != null) {
serialPort.close();
}
bPortOpen = false;
System.out.println("closePort() is execute ");
}
private OutputStream getOutputStream() {
if (serialPort == null) {
try {
openPort();
} catch (Exception e) {
log.error("", e);
return null;
}
}
try {
return serialPort.getOutputStream();
} catch (IOException e) {
throw new CommException("COMERR-005", e);
}
}
//发送RFIP命令
public synchronized void sendCommand(Command command) {
byte msg[];
if (command == null)
return;
msg = (byte[]) command.getBody();
if (log.isDebugEnabled())
log.info((new StringBuilder("Send command: ")).append(
ByteUtil.toHex(msg)).toString());
last = null;
commandFlag = true;
try {
if(serialPort.getOutputStream()==null){
commandFlag=false;
return;
}
} catch (Exception e) {
return;
}
try {
getOutputStream().write(msg);
getOutputStream().flush();
commandResponseParser.setCommand(command);
long begin = System.currentTimeMillis();
boolean timeout = false;
while (commandFlag) {
if (System.currentTimeMillis() - begin >= command.waitTime()) {
timeout = true;
break;
}
try {
Thread.sleep(1000L);
} catch (InterruptedException interruptedexception) {
}
}
if (log.isDebugEnabled())
log.debug((new StringBuilder("timeout: ")).append(timeout)
.toString());
if (timeout) {
startTime = 0;
}
if (log.isDebugEnabled())
log.debug("consume response");
command.consume();
} catch (IOException e) {
throw new CommException("COMERR-005", e);
}
commandFlag = false;
return;
}
// 解析指令执行后响应字符
public void consume(Machine machine, Object response) {
byte res[] = (byte[]) response;
HashSet cards = new HashSet();
if (res[3] == 85) {
int number = (0xff & res[2] - 3) / 2;
for (int i = 0; i < number; i++) {
byte b = res[4 + i * 2];
byte c = res[5 + i * 2];
int ci = 0x10000 + ((0x7f & b) << 8) + (0xff & c);
String cardId = Integer.toHexString(ci).toUpperCase()
.substring(1);
if (!cards.contains(cardId)) {
cards.add(cardId);
log.info("==machineid====:::::::"+res[1]+"===cardId===::::::"+cardId);
MachineService ms;
com.farp.bean.Machine ma=new com.farp.bean.Machine();
/*持久化到数据库中*/
}
}
}
}
// public void run() {} 写一个空的线程发放,让子类实现它。
public void run() {
try {
producer = new HrPassiveCommandProducer();
while (true) {
/*----------------------- 重点在这里 -------------------------
这里有两个方法:1,是监听一个事务,需要长时间一次监听,大概一小时,所以if里面是判断时间的。
2,是每一秒钟都需要监听。
而现在的情况是,每一秒钟都要判断一次 1 方法,效率很低,
所以要做成线程分离,做两个子类,test1,test2继承这个类,把这个run()给注释掉,写个空的,
我的思路是:在2方法中加个循环控制,循环3600次,就是一小时,然后放弃监听,把监听给1方法,
1方法走一次,然后放弃监听,给2方法。
现在的问题是:我找不到把监听对象替换的办法,removeEventListener()好像是关闭监听,而不是消除对象!
*/
//1方法,发送检测读卡器指令
if(startTime == 0 || (System.currentTimeMillis() - startTime) > readMachineInterval){
Command command = producer.getCommand(null, Command.GET_MACHINE_ID, 0);
//发送命令
sendCommand(command);
startTime = System.currentTimeMillis();
try {
machineList = command.getAnswerMachineIds();
} catch (Exception e) {
startTime = 0;
}
}
//2方法,给每个可用的读卡器发送读取标签的指令
if(machineList!=null && machineList.size()>0){
for(int x=0;x<machineList.size();x++){
// 设置参数
Machine machine=new Machine();
machine.setMachineId(new Integer(machineList.get(x).toString()));
Command command = producer.getCommand(machine,
Command.READ_DATA, 0);
// 发送命令
sendCommand(command);
}
}
Thread.sleep(1000);
}
} catch (InterruptedException e) {
}
}
// 监听自动调用的类方法
public void serialEvent(SerialPortEvent event) {
System.out.println("进入监听。");
switch (event.getEventType()) {
case SerialPortEvent.BI:
case SerialPortEvent.OE:
case SerialPortEvent.FE:
case SerialPortEvent.PE:
case SerialPortEvent.CD:
case SerialPortEvent.CTS:
case SerialPortEvent.DSR:
case SerialPortEvent.RI:
case SerialPortEvent.OUTPUT_BUFFER_EMPTY:
break;
case SerialPortEvent.DATA_AVAILABLE:
try {
InputStream in = serialPort.getInputStream();
byte buf[] = new byte[50];
ByteArrayOutputStream os = new ByteArrayOutputStream();
int numBytes;
for (; in.available() > 0; os.write(buf, 0, numBytes))
numBytes = in.read(buf);
byte message[] = os.toByteArray();
if (message.length > 0) {
if (log.isDebugEnabled())
log.debug((new StringBuilder("Received: ")).append(
ByteUtil.toHex(message)).toString());
if (message[0] != 170
|| !ByteUtil.endsWith(last, Command.SUFFIX)) {
byte msg[];
if (last != null) {
msg = new byte[last.length + message.length];
System.arraycopy(last, 0, msg, 0, last.length);
System.arraycopy(message, 0, msg, last.length,
message.length);
} else {
msg = message;
}
message = msg;
}
last = message;
if (commandResponseParser.satisified(message) && commandFlag) {
commandFlag = false;
last = null;
}
}
} catch (IOException e) {
e.printStackTrace();
}
break;
}
}
//启动线程
public static void main(String[] args) {
PortOperate po = new PortOperate();
po.startThread();
}
public void startThread(){
if (this.searchPort()) {
readThread = new Thread(this);
readThread.start();
}
}
}
public class Test1 extends PortOperate {
private List machineList = new ArrayList();
public void run() {
try {
producer = new HrPassiveCommandProducer();
while (true) {
//发送检测读卡器指令
if(startTime == 0 || (System.currentTimeMillis() - startTime) > readMachineInterval){
Command command = producer.getCommand(null, Command.GET_MACHINE_ID, 0);
//发送命令
sendCommand(command);
startTime = System.currentTimeMillis();
try {
machineList = command.getAnswerMachineIds();
// setMachineList(machineList); 传递machineList集合给test2类用。
} catch (Exception e) {
startTime = 0;
}
System.out.println("--- PortOperateLong ---");
}
Thread.sleep(1000*60*60);//休眠一小时
// removeEventListener(); 这里的消除监听对象不管用,
// addEventListener(new Test2()); 所以就不能新添加test2类。
}
} catch (InterruptedException e) {
}
}
public List getMachineList() {
return machineList;
}
public void setMachineList(List machineList) {
this.machineList = machineList;
}
}
**************Test2类***************
public class Test2 extends PortOperate {
long longtime = 3600; // 循环次数,这个是限定时间的。一小时
public void run() {
try {
Machine machine=new Machine();
producer = new HrPassiveCommandProducer();
machineList.add(7);
machineList.add(8);
// machineList = pol.getMachineList();
while (true) {
//给每个可用的读卡器发送读取标签的指令
for(int i=0;i<longtime;i++){ // 循环次数,这个是限定时间的。一小时
if(machineList!=null && machineList.size()>0){
for(int x=0;x<machineList.size();x++){
// 设置参数
machine.setMachineId(new Integer(machineList.get(x).toString()));
Command command = producer.getCommand(machine,
Command.READ_DATA, 0);
// 发送命令
sendCommand(command);
}
}
Thread.sleep(1000);
}
// removeEventListener(); 这里的消除监听对象不管用,
// addEventListener(new Test1()); 所以就不能新添加test1类。
}
} catch (InterruptedException e) {
}
}
}
Test1 t1 = new Test1();
Test1 t2 = new Test2();
在t2类中这样实例化后,调用addEventListener(t1)时候就会报异常。
不知道为什么。但是调用自己却不会出现异常addEventListener(this)。
时间一小时一次,所以再移除监听对象serialPort.removeEventListener(),
把对象给serialPort.addEventListener(t2),但是这里给添加监听对象t2时候,肯定的用到实例化test2类,这里就出现了问题,报异常啦!!!
怎么办呀!!
不能把线程分离出来吗?
我试过用test1类把自己的监听移除.removeEventListener();然后再把自己加上:serialPort.addEventListener(t1);
这样也能通过,还是继续监听自己,但是只要把t1换成t2,就是添加为空,没有添加到t2。
这个我也测试了一下,把监听serialPort.addEventListener(this);封装到一个方法中,这个方法,是添加谁,就要实例化谁,用实例化后的对象调用这个方法,这样才能添加自己,不能添加别的类。
最最重要的是在test1,test2类中都不能互相实例化对象,真是郁闷啊!!!
求高手帮忙呀!!做过类似串口编程的高手帮忙呀!
小弟真是急死啦!!!!