我有 3 个 rfid 阅读器,我正在阅读 rfid 标签。 我正在运行这些,但由于某种原因,我只从正在处理的最后一个读取器(线程(接收信息。 我错过了什么?读取器位于包含 IP 地址、用户名、端口、密码的数组中。我可以收听所有相同的服务吗?我是线程的新手...TagInventory 是所有这些所在的类的名称。
这是代码:
private void Start() throws AlienReaderException, IOException{
ThreadStop = false;
service= new MessageListenerService(3900);
service.setMessageListener(this);
service.startService();
System.out.println("length of readers: "+Reader.ipAddress.length);
for (lastThreadId = 0; lastThreadId < Reader.ipAddress.length; lastThreadId++)
{
m_inventory[lastThreadId] = new AlienReader(Reader.ipAddress[lastThreadId], Reader.port, Reader.username[lastThreadId], Reader.password[lastThreadId]);
log.info("taginventory reader: "+ Reader.ipAddress[lastThreadId]+"Thread: "+lastThreadId);
m_run_process[lastThreadId] = new Thread(new StartInventoryThread(Reader.ipAddress[lastThreadId], Reader.port, Reader.username[lastThreadId], Reader.password[lastThreadId], m_inventory[lastThreadId]));
m_run_process[lastThreadId].start();
}
--lastThreadId;
try
{
// Thread.sleep(1000);
Thread.sleep(2000);
}
catch (Exception ex)
{
ex.getMessage();
}
}
class StartInventoryThread implements Runnable{
private String ip;
private int port;
private String user;
private String pwd;
private AlienReader ar;
StartInventoryThread(String ip, int port, String user, String pwd, AlienReader ar){
this.ip=ip;
this.port=port;
this.user=user;
this.pwd=pwd;
this.ar=ar;
}
@Override
public void run() {
try {
while(!stopInventory){
startRead(ip,port,user,pwd);
}
} catch (AlienReaderException | InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public void startRead(String ip, int port, String user, String password) throws AlienReaderException, InterruptedException, UnknownHostException{
String myIP=InetAddress.getLocalHost().getHostAddress();
//System.out.println("ip"+ ip);
AlienReader ar= new AlienReader(ip, port, user, password);
ar.open();
//log.info("Reader" + ar.getIPAddress());
ar.setNotifyAddress(myIP, 3900);
ar.setNotifyFormat(AlienClass1Reader.TEXT_FORMAT);
//ar.setNotifyTrigger("TrueFalse");
ar.setNotifyTrigger("Add");
ar.setNotifyMode(AlienClass1Reader.ON);
// log.info("MessageListenerService has started for reader: " + ip);
//complete process in here
ar.autoModeReset();
ar.setAutoStopTimer(5000); // Read for 5 seconds
ar.setAutoMode(AlienClass1Reader.ON);
tagTable.setTagTableListener(tagTableListener);
tagTable.setPersistTime(3600);
//tagTable.setPersistTime(1800000);
ar.close();
long runTime = 10000; // milliseconds
long startTime = System.currentTimeMillis();
do {
Thread.sleep(1000);
} while(service.isRunning()
&& (System.currentTimeMillis()-startTime) < runTime);
// Reconnect to the reader and turn off AutoMode and TagStreamMode.
// log.info("nResetting Reader");
ar.open();
ar.autoModeReset();
ar.setNotifyMode(AlienClass1Reader.OFF);
ar.close();
}
public static void main(String args[]){
Thread thr=new Thread(new Runnable(){
@Override
public void run(){
try {
new TagInventory();
} catch (AlienReaderException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
thr.start();
}
概述
我在整个代码中看到了您的逻辑中的许多问题和潜在危险。我将逐步介绍每个概念,并引导您找到与这些问题一致的相应概念。
主要
在main(String args[])
中添加一个join()
调用,以便调用线程(可能是主线程(可以等到Thread thr
完成再退出。
public static void main(String args[]){
Thread thr=new Thread(new Runnable(){
@Override
public void run(){
try {
new TagInventory();
} catch (AlienReaderException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
thr.start();
thr.join();
}
开始
假设您期望线程在Start()
函数完成时完成,我将解释如何获得该功能。不要使用Thread.sleep()
因为它被认为是糟糕的编程。而是利用join()
功能。强制调用线程等待或阻塞,直到该线程完成。下面添加的逻辑将循环遍历每个m_run_process
并阻止,直到完成。如果您有另一个位置想要确保它们都完成,则可以将for-loop
放在那里。
private void Start() throws AlienReaderException, IOException{
ThreadStop = false;
service= new MessageListenerService(3900);
service.setMessageListener(this);
service.startService();
System.out.println("length of readers: "+Reader.ipAddress.length);
for (lastThreadId = 0; lastThreadId < Reader.ipAddress.length; lastThreadId++)
{
m_inventory[lastThreadId] = new AlienReader(Reader.ipAddress[lastThreadId], Reader.port, Reader.username[lastThreadId], Reader.password[lastThreadId]);
log.info("taginventory reader: "+ Reader.ipAddress[lastThreadId]+"Thread: "+lastThreadId);
m_run_process[lastThreadId] = new Thread(new StartInventoryThread(Reader.ipAddress[lastThreadId], Reader.port, Reader.username[lastThreadId], Reader.password[lastThreadId], m_inventory[lastThreadId]));
m_run_process[lastThreadId].start();
}
--lastThreadId;
for(Thread inventoryThread : m_run_process)
inventoryThread.join()
}
开始阅读
这里似乎有很多问题,您访问非线程安全的对象和变量;service
、stopInventory
和tagTable
(没有看到完整的文件,我正在做假设,我在任何地方都看不到同步(。现在,我建议阅读Java内存模型,Java内存屏障,原子操作,同步,线程安全和JVM。实质上,您的逻辑可能会导致覆盖数据和/或线程看到不同的缓存值。要纠正此问题,您必须通过同步和原子性使共享的可变实例成为线程安全的实例。
public void startRead(String ip, int port, String user, String password) throws AlienReaderException, InterruptedException, UnknownHostException{
String myIP=InetAddress.getLocalHost().getHostAddress();
//System.out.println("ip"+ ip);
AlienReader ar= new AlienReader(ip, port, user, password);
ar.open();
//log.info("Reader" + ar.getIPAddress());
ar.setNotifyAddress(myIP, 3900);
ar.setNotifyFormat(AlienClass1Reader.TEXT_FORMAT);
//ar.setNotifyTrigger("TrueFalse");
ar.setNotifyTrigger("Add");
ar.setNotifyMode(AlienClass1Reader.ON);
// log.info("MessageListenerService has started for reader: " + ip);
//complete process in here
ar.autoModeReset();
ar.setAutoStopTimer(5000); // Read for 5 seconds
ar.setAutoMode(AlienClass1Reader.ON);
tagTable.setTagTableListener(tagTableListener);
tagTable.setPersistTime(3600);
//tagTable.setPersistTime(1800000);
ar.close();
long runTime = 10000; // milliseconds
long startTime = System.currentTimeMillis();
do {
Thread.sleep(1000);
} while(service.isRunning()
&& (System.currentTimeMillis()-startTime) < runTime);
// Reconnect to the reader and turn off AutoMode and TagStreamMode.
// log.info("nResetting Reader");
ar.open();
ar.autoModeReset();
ar.setNotifyMode(AlienClass1Reader.OFF);
ar.close();
}