----------------------- 重点在这里 -------------------------
这里有两个方法: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.   

    代码有点长,所以分开来传了!       //线程自动调用的方法
    // 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();
    }
    }
    }
      

  2.   

    这个是我写的两个继承类:**************Test1类***************
    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) {
    }
    }
    }
      

  3.   

    还有,我不能在子类中Test1,Test2中,实例化Test1,Test2对象,
    Test1 t1 = new Test1();
    Test1 t2 = new Test2();
    在t2类中这样实例化后,调用addEventListener(t1)时候就会报异常。
    不知道为什么。但是调用自己却不会出现异常addEventListener(this)。
      

  4.   

    现在弄明白serialPort.removeEventListener()是去掉监听对象了。问题是:在t1类中先得到监听对象serialPort.addEventListener(this);
    时间一小时一次,所以再移除监听对象serialPort.removeEventListener(),
    把对象给serialPort.addEventListener(t2),但是这里给添加监听对象t2时候,肯定的用到实例化test2类,这里就出现了问题,报异常啦!!!
    怎么办呀!!
      

  5.   

    是我的思路有问题呢,还是这种逻辑是不行啊?
    不能把线程分离出来吗?
    我试过用test1类把自己的监听移除.removeEventListener();然后再把自己加上:serialPort.addEventListener(t1); 
    这样也能通过,还是继续监听自己,但是只要把t1换成t2,就是添加为空,没有添加到t2。
    这个我也测试了一下,把监听serialPort.addEventListener(this);封装到一个方法中,这个方法,是添加谁,就要实例化谁,用实例化后的对象调用这个方法,这样才能添加自己,不能添加别的类。
    最最重要的是在test1,test2类中都不能互相实例化对象,真是郁闷啊!!!
    求高手帮忙呀!!做过类似串口编程的高手帮忙呀!
    小弟真是急死啦!!!!