下面以List结合为例子,
先来看以下代码:
public static ArrayListdatas=new ArrayList ();//初始化数据 public static void initData(){ for(int i=0;i<20;i++){ datas.add(""+i); } } //线程1,读取集合的数据 public static Thread thread1=new Thread(){ public void run() { //int size=datas.size(); for(String data:datas){ System.out.println(data); } }; };//线程2,删除集合的数据 private static Thread thread2=new Thread(){ public void run() { int size=datas.size(); for(int i=0;i
这样子运行的话,肯定会出一个异常。下面请看执行的结果 remove remove 1 remove remove remove remove remove remove Exception in thread "Thread-0" remove remove remove remove remove remove remove remove remove remove remove remove java.util.ConcurrentModificationException at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:819) at java.util.ArrayList$Itr.next(ArrayList.java:791)
在现实编程环境中,经常会遇到既需要遍历集合,又需要在另一个线程中删除集合。那么怎么解决呢?
下面就来解决这个问题,我们用到了位于java.util.concurrent.locks包里面的ReentrantReadWriteLock;
简称读写锁,它有两个核心的方法,分别是readLock()和writeLock(),即获取读锁和写锁。获取读锁的前提是写锁没有锁住。获取写锁的前提是读锁没有锁住。也就是保证在读的时候就没有人在写数据或者修改数据。在写数据或者修改数据的时候就没有人在读数据。就好像我们编辑word文档一样,在编辑状态,就不允许移动,复制。根据这个原理,我们接下来改进代码如下:
public static final ReadWriteLock lock = new ReentrantReadWriteLock(false); public static ArrayListdatas=new ArrayList (); public static void initData(){ for(int i=0;i<20;i++){ datas.add(""+i); } } public static Thread thread1=new Thread(){ public void run() { lock.readLock().lock(); for(String data:datas){ System.out.println("t1 "+data); } lock.readLock().unlock(); }; }; public static Thread thread3=new Thread(){ public void run() { lock.readLock().lock(); for(String data:datas){ System.out.println("t3 "+data); } lock.readLock().unlock(); }; }; private static Thread thread2=new Thread(){ public void run() { int size=datas.size(); lock.writeLock().lock(); for(int i=0;i
这时候程序执行结果是:
t1 0
t1 1 t1 2 t1 3 t1 4 t1 5 t1 6 t1 7 t1 8 t1 9 t1 10 t1 11 t1 12 t1 13 t1 14 t1 15 t1 16 t1 17 t1 18 t1 19 remove remove remove remove remove remove remove remove remove remove remove remove remove remove remove remove remove remove remove removepublic static void main(String[] args) { initData(); thread1.start(); thread3.start(); thread2.start(); }
t3 0 t1 0 t3 1 t1 1 t3 2 t1 2 t3 3 t1 3 t3 4 t1 4 t3 5 t1 5 t3 6 t1 6 t3 7 t1 7 t3 8 t1 8 t3 9 t1 9 t3 10 t1 10 t3 11 t1 11 t3 12 t1 12 t3 13 t1 13 t3 14 t1 14 t3 15 t1 15 t1 16 t1 17 t3 16 t1 18 t1 19 t3 17 t3 18 t3 19 remove remove remove remove remove remove remove remove remove remove remove remove remove remove remove remove remove remove remove remove