一個(gè)工具類中有個(gè)監(jiān)聽集合(LinkedList listeners),添加和刪除都通過(guò)synchronized的regist和unregist方法處理拼窥,但是在對(duì)其監(jiān)聽集合進(jìn)行synchronized 的 for循環(huán)處理數(shù)據(jù)時(shí)還是出現(xiàn)了IndexOutOfBoundsException戏蔑,百思不得其解。
public abstract class MapLocation {
private LinkedList<ILocationListener> listeners = new LinkedList<ILocationListener>();
public boolean registLocationListener(ILocationListener listener) {
if (listener == null) {
return false;
}
synchronized (listeners) {
if (listeners.contains(listener)) {
return false;
}
listeners.add(listener);
return true;
}
}
public boolean unregistLocationListener(ILocationListener listener) {
if (listener == null) {
return false;
}
synchronized (listeners) {
return listeners.remove(listener);
}
}
protected void dispatchLocation(final LocationEntry le) {
synchronized (listeners) {
int size = listeners.size();
// for (int i = 0; i < size; i++) { //1
for (int i = size - 1; i > 0; i--) {//3
listeners.get(i).onLocationReceive(null, le);
}
}
}
protected void dispatchLocationFailed() {
synchronized (listeners) {
int size = listeners.size();
// for (int i = 0; i < size; i++) {//2
for (int i = size - 1; i > 0; i--) {//4
listeners.get(i).onLocationFailed();
}
}
}
public static interface ILocationListener {
public void onLocationReceive(String fromHID, LocationEntry le);
void onLocationFailed();
}
}
既然出現(xiàn)了IndexOutOfBoundsException鲁纠,說(shuō)明監(jiān)聽集合在循環(huán)過(guò)程中肯定被修改了辛臊,導(dǎo)致。既然已經(jīng)同步房交,說(shuō)明修改不可能其他線程在循環(huán)外部彻舰,只可能在循環(huán)的內(nèi)部出現(xiàn)。最后終于發(fā)現(xiàn)在listener的實(shí)現(xiàn)中會(huì)調(diào)用unregist方法將當(dāng)前l(fā)istener從集合中remove候味。而循環(huán)中是從頭到尾(1,2)獲取每個(gè)數(shù)據(jù)項(xiàng)目刃唤,并從集合中remove掉自己,size是提前獲取好的白群。這樣導(dǎo)致集合中的數(shù)據(jù)跟size對(duì)不上尚胞。從而出現(xiàn)越界異常。
解決:如果循環(huán)從尾到頭獲取帜慢,雖然尾部的數(shù)據(jù)項(xiàng)目被remove掉笼裳,但是下次循環(huán)的index總是從上次remove掉的上一個(gè),因此并無(wú)影響粱玲。
注意:如果刪除時(shí)同一次循環(huán)同時(shí)刪除多個(gè)數(shù)據(jù)項(xiàng)目躬柬。則會(huì)導(dǎo)致下一次循環(huán)取數(shù)據(jù)時(shí)拿不到數(shù)據(jù)報(bào)空指針異常,此時(shí)解決方法只有一個(gè)在另外的線程中刪除(Iterator 或者自建線程抽减。Iterator其實(shí)是在另外的線程中運(yùn)行)允青。