62,614
社区成员
发帖
与我相关
我的任务
分享
//线程1---生产数据
public class DataForWlan extends Thread {
private CardReaderForWlan rr;
public static Set<String> carIdAndTimeSet = Collections.synchronizedSet( new HashSet<String>());
public Set<String> getCarIdAndTimeSet() {
return carIdAndTimeSet;
}
public void setCarIdAndTimeSet(Set<String> carIdAndTimeSet) {
this.carIdAndTimeSet = carIdAndTimeSet;
}
// 初始化线程类
private void init() {
try {
rr = new CardReaderForWlan(); //创建无线读卡连接
} catch (ReaderException e) {
e.printStackTrace();
return;
}
if (rr == null) {
return;
}
}
public synchronized void run() {
init();
try {
while (true) {
TagReadData[] trd = rr.MultiReadCard(); //不断的读卡 但不一定每时每刻都有数据产生
if (trd.length > 0) {
readCar(trd);
}
//this.sleep(5);
}
} catch (Exception e) {
this.stop();
e.printStackTrace();
}
}
/**
* 处理需要的数据
*/
public void readCar(TagReadData[] trd) {
try {
int trdLength = trd.length;
if (trdLength <= 0) {
return;
}
for (int i = 0; i < trdLength; i++) {
String cardID = trd[i].EPCHexstr(); //卡ID
String carIdAndTime = cardID +","+ System.currentTimeMillis()/1000;//用于线程2处理数据用
carIdAndTimeSet.add(carIdAndTime);//短时间内会读一张卡几次,但只需要一结果即可
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 清空数据
*/
public void clearcarIdAndTimeSet(){
carIdAndTimeSet.clear();
}
}
public class MainJFrame extends javax.swing.JFrame implements ActionListener , Runnable{
public Set<String> carIAndTime =null;//读到的卡号存放
public Set<String> cardIdlist = new HashSet<String>();//显示面板存放卡号
public DataForWlan dfw= new DataForWlan ();//无线读卡器线程
public void run() {
while (true) {
try {
carIAndTime = new HashSet<String>();
carIAndTime.addAll(dfw.getCarIdAndTimeSet());//将线程1中的值赋值给carIAndTime
dfw.clearcarIdAndTimeSet();//清空数据
if(carIAndTime.size()!=0){
Iterator<String> iterator = carIAndTime.iterator();
while(iterator.hasNext()){
String cardTime = iterator.next();
String [] strs = cardTime.split("[,]");
String cardID = strs[0];//卡ID
user = listAllUsers.get(strs[0]);//根据卡ID得到签到人员
if(user != null){
long time = Long.valueOf(strs[1]);
Iterator<String> keys = map.keySet().iterator();
if(keys.hasNext()){//以下是做业务处理可以忽略
boolean re = isExist(map, cardID);
if(re){//存在
long aftertime = map.get(cardID);//前一个时间
if (time - aftertime > 30) {
map.put(strs[0], Long.valueOf(strs[1]));
cardIdlist.add(strs[0]);
}
}else{
map.put(strs[0], Long.valueOf(strs[1]));
cardIdlist.add(strs[0]);
}
}else{
map.put(strs[0],Long.valueOf(strs[1]));
cardIdlist.add(strs[0]);
}
setCarIdOfTime(cardIdlist);//将得到数据,进行业务处理
cardIdlist.clear();
iterator.remove();//后来加的
}
}
}
Thread.currentThread().sleep(600);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public boolean isExist(Map<String, Long> map, String abc){
boolean isexit = false;
Iterator<String> keys = map.keySet().iterator();
if(keys.hasNext()){
while (keys.hasNext()) {
String key = (String)keys.next();
if (abc.equals(key)) {//判断此卡号在map中不存在
return true;
}
}
}
return isexit;
}
}
Exception in thread "Thread-4" java.util.ConcurrentModificationException
at java.util.HashMap$HashIterator.nextEntry(Unknown Source)
at java.util.HashMap$KeyIterator.next(Unknown Source)
at java.util.AbstractCollection.addAll(Unknown Source)
at indexframes.MainJFrame.run(MainJFrame.java:380)
at java.lang.Thread.run(Unknown Source)
//380行就是线程2中的
carIAndTime.addAll(dfw.getCarIdAndTimeSet());
iterator.remove();//后来加的
List<String> list = new ArrayList<String>();
list.add("aaa");
list.add("bbb");
list.add("ccc");
Iterator<String> iterator = list.iterator();//迭代的时候
while(iterator.hasNext()){
String s = iterator.next();
list.remove(s);//外部修改是不行的
//iterator.remove();//内部修改时可以的
}
System.out.println(list.size());
那么LZ报错的那个地方
carIAndTime.addAll(dfw.getCarIdAndTimeSet());/
看看AbstractCollection的源码就知道了
public boolean addAll(Collection<? extends E> c) {
boolean modified = false;
Iterator<? extends E> e = c.iterator();
while (e.hasNext()) {
if (add(e.next()))
modified = true;
}
return modified;
}
addAll方法也用到了迭代器,这个方法的入参来自你第一个线程,在迭代的时候即addAll的那一刻,被线程1给改了,就会抛出
java.util.ConcurrentModificationException
而且你这是生产者消费者模式,不能用set,要用queue,即是是多次读,也要用queue包装一下carIAndTime.addAll(new HashSet<String>(dfw.getCarIdAndTimeSet()));
却又是 hashset,怪哉
private Map<String, Long> map = new ConcurrentHashMap<String,Long>();
carIAndTime.addAll(new HashSet<String>(dfw.getCarIdAndTimeSet()));