我有3个RFID阅读器,正在阅读RFID标签。我正在运行这些,但是由于某种原因,我仅从正在处理的最后一个reader(thread)接收信息。我想念什么?阅读器位于包含ipaddress,用户名,端口,密码的数组中。我可以为所有人收听同一服务吗?我是线程的新手。........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();
}
答案 0 :(得分:0)
概述
在整个代码中,我发现您的逻辑中存在许多问题和潜在危害。我将逐一介绍并指导您解决与这些问题相适应的相应概念。
主要
在您的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()
函数。强制调用线程等待或 block 直到该线程完成。下面添加的逻辑将循环遍历m_run_process
和 block 直到完成。如果您要确保其他位置都可以完成,则可以将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内存屏障,原子操作,同步,< strong>线程安全和 JVM 。本质上,您的逻辑可能会导致数据和/或线程被覆盖,从而看到不同的 cache 值。要进行纠正,您必须通过同步和原子性使共享的可变实例成为线程安全的。
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();
}