美文网首页
For 循环中遇到的一个IndexOutOfBoundsExce

For 循环中遇到的一个IndexOutOfBoundsExce

作者: W_W_ | 来源:发表于2017-08-18 22:42 被阅读12次

    一个工具类中有个监听集合(LinkedList listeners),添加和删除都通过synchronized的regist和unregist方法处理,但是在对其监听集合进行synchronized 的 for循环处理数据时还是出现了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();
        }
    } 
    

    既然出现了IndexOutOfBoundsException,说明监听集合在循环过程中肯定被修改了,导致。既然已经同步,说明修改不可能其他线程在循环外部,只可能在循环的内部出现。最后终于发现在listener的实现中会调用unregist方法将当前listener从集合中remove。而循环中是从头到尾(1,2)获取每个数据项目,并从集合中remove掉自己,size是提前获取好的。这样导致集合中的数据跟size对不上。从而出现越界异常。
    解决:如果循环从尾到头获取,虽然尾部的数据项目被remove掉,但是下次循环的index总是从上次remove掉的上一个,因此并无影响。
    注意:如果删除时同一次循环同时删除多个数据项目。则会导致下一次循环取数据时拿不到数据报空指针异常,此时解决方法只有一个在另外的线程中删除(Iterator 或者自建线程。Iterator其实是在另外的线程中运行)。

    相关文章

      网友评论

          本文标题:For 循环中遇到的一个IndexOutOfBoundsExce

          本文链接:https://www.haomeiwen.com/subject/sirzrxtx.html