基于XML的数据库开发-6


    最新一直工作比较忙,一直木有空继续写这个数据库。

    今天主要解决的是数据读写移除的冲突问题。

    数据库设计的时候是按照内存数据库来构思的,所以所有的数据实际上都是保存在ArrayList中的。

    因此会出现如下的问题:

    -----------------------------------------

    线程1正在循环读取数据

     for(DataCell:dataList) {

          //TODO

     }

     此时线程2又对数据进行了删除操作

         dataList.remove(1)

扫描二维码关注公众号,回复: 5890843 查看本文章

    -----------------------------------------

    这个时候,JAVA就会报java.util.ConcurrentModificationException。

    针对上述情况,我们一般可能想到的对应方法是使用synchronized。

    synchronized(dataList) {

        for(DataCell:dataList) {

              //TODO

         }

    }

    synchronized(dataList) {

        dataList.remove(1)

    }

    这样的写法的确可以通过同步来控制,但是如果我有3个线程,其中2个线程

    只是循环读取数据, 如果使用如上写法,就会造成1个线程读取完毕,另外一个线程继续读取的现象。

     会影响读取的效率。


     回过头来仔细想一下,其实我们只是希望将add/remove和循环read的操作进行乎斥即可。

     即循环read的时候不能对dataList进行操作。而删除的时候也不能进行循环读写。


     按照上述的思想,我们可以有2个方法(不是很完美,但是能解决这个问题)

     方法1.规定只用使用foreach语法来循环调用这个数组。且不能中途推出循环

                 这样,我们就可以复写iretor,将hastnext认为是循环开始的触发函数,netx()为null的时候认为是循环结束的条件。

                 但是这样的规定比较固定,所以可能导致程序编写有很多限制.暂时没有使用这个方法.

                 示例代码如下:

class DataCellList extends ArrayList<Integer>{


boolean isCanRemove = false;

class myIteratorDector implements Iterator<Integer>{


public Iterator dectorIre;

public myIteratorDector(Iterator ite) {
dectorIre = ite;
}

@Override
public boolean hasNext() {
System.out.println("iterator hasnext");
return dectorIre.hasNext();
}


@Override
public Integer next() {
System.out.println("iterator next");
            Integer nextV = (Integer) dectorIre.next();
return nextV;
}


@Override
public void remove() {
dectorIre.remove();
}

}

/**
* 
*/
private static final long serialVersionUID = 1L;

    public Iterator<Integer>iterator()  {
    System.out.println("iterator");
    return new myIteratorDector(super.iterator());
    }
}


 

     方法2:增加2个接口来表示进入循环和退出循环,进入循环的时候,判断当前是否有remove的操作,如果有,就开始等待.  如果remove操作结束.接口继续作如下处理:循环计数器+1 循环结束的时候,调用退出循环接口,则循环计数器-1,然后确认是否有remove操作应为这个循环而在wait,如果有则激活remove处理.

      相关代码:

public class DataCellList extends ArrayList<DataCell>{
    private int currentInLoop = 0;
    private int currentInRemoving = 0;
    
    private Object mWaitForLoopObj = new Object();
    private Object mWaitForRemoveAddObj = new Object();
    
    public void enterLooper() {
    	
    	//DebugThread debugThread = new DebugThread();
    	//debugThread.start();
    	
    	if(currentInRemoving != 0) {
    		try {
    			synchronized(mWaitForRemoveAddObj) {
    			    mWaitForRemoveAddObj.wait();
    			}
			} catch (InterruptedException e) {
				LogUtil.e(TAG, "setRemovingFlag error" + e.toString());
			}
    	}
    	
    	currentInLoop++;
    }
    
    public void leaveLooper() {
    	currentInLoop--;
    	
    	if(currentInLoop == 0) {
    		synchronized(mWaitForLoopObj) {
    	        mWaitForLoopObj.notify();
    		}
	    }
    }
    
    public boolean add(DataCell data) {
        data.setId(this.size());
        setRemoveAddFlag();
        boolean result = super.add(data);
        clearRemoveAddFlag();
        
        return result;
    }
    
    public DataCell remove(int index) {
    	//this method is fobbiden
    	setRemoveAddFlag();
    	DataCell result = super.remove(index);
    	clearRemoveAddFlag();
    	return result;
    }

    private void setRemoveAddFlag() {
    	if(currentInLoop != 0) {
    		try {
    			synchronized(mWaitForLoopObj) {
				    mWaitForLoopObj.wait();
    			}
			} catch (InterruptedException e) {
				LogUtil.e(TAG, "setRemovingFlag error" + e.toString());
			}
    	}
    	
    	currentInRemoving++;
    }
    
    private void clearRemoveAddFlag() {
    	currentInRemoving--;
    	if(currentInRemoving == 0) {
    		synchronized(mWaitForRemoveAddObj) {
    		    mWaitForRemoveAddObj.notify();
    		}
    	}
    }



}


 

                

                 

猜你喜欢

转载自blog.csdn.net/wang_sun_1983/article/details/11785435