java并发集合_Java并发集合操作中对锁的应用。

下面以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

datas.remove(0);

System.out.println("remove");

}

};

};

//启动程序

public static void main(String[] args) {

initData();

thread1.start();

thread2.start();

}

这样子运行的话,肯定会出一个异常。下面请看执行的结果

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

datas.remove(0);

System.out.println("remove");

}

lock.writeLock().unlock();

};

};

public static void main(String[] args) {

initData();

thread1.start();

thread2.start();

thread3.start();

}

这时候程序执行结果是:

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

remove

大家可能疑惑为啥没有t3的打印呢?因为读锁在释放之后,立马就被写锁占用了,写锁的线程把集合清空了,所以当轮到线程3的时候就没有数据了,多试几次,会发现还有一种执行结果就是全部都是remove。没有任何打印,这是因为先执行了线程2的缘故。如果我们按照这样的顺序执行,又会不同:

public 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

可以看到读锁在不同的线程中是不排斥的。好的,就为大家介绍到这里。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值