您的位置:首页 > 其它

关于ConcurrencyHashmap的并发问题

2016-09-25 00:21 746 查看
看这段代码
package concurrencyTest;

import java.util.Iterator;
import java.util.concurrent.ConcurrentHashMap;

public class ConcurrencyTest2 {

/**
* @param args
*/
public static void main(String[] args) {
ConcurrentHashMap<Integer, Integer>  map = new ConcurrentHashMap<Integer, Integer>() ;
for(int i=500;i<600 ; i++)
map.put(i, i+111111) ;

long start = System.currentTimeMillis() ;
Thread t1 = new Thread(new Producer(map)) ;
Thread t2 = new Thread(new Consumer(map)) ;

t1.start();
t2.start();

try {
t1.join() ;
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Read last : " + (System.currentTimeMillis() - start) + " ms" + " shareMap : " + map.size());
}
}

class Producer implements Runnable {
ConcurrentHashMap<Integer, Integer>  sharemap ;
int num = 0 ;

public Producer(ConcurrentHashMap<Integer, Integer> map) {
sharemap = map ;
}

@Override
public void run() {
int i =0 ;
while(i<10) {
add(i) ;
i++ ;
}
System.out.println(Thread.currentThread().getName() + " add " + 10 + " elements! ShareMap size: " + sharemap.size() );
}

public void add(int item) {  //该方法线程不安全
if(!sharemap.containsKey(item)) {
sharemap.putIfAbsent(item, item + 111111) ;
} else {
sharemap.put(item, sharemap.get(item) + 111111) ;
}
}
}

class Consumer implements Runnable {
ConcurrentHashMap<Integer, Integer>  sharemap ;
int num = 0 ;

public Consumer(ConcurrentHashMap<Integer, Integer> map) {
sharemap = map ;
}

@Override
public void run() {
it = sharemap.values().iterator();
Integer i = poll();
while(i!=null) {
i = poll() ;
num++ ;
}
System.out.println(Thread.currentThread().getName() + " poll " + num + " elements! ShareMap size: " + sharemap.size() );
}

Iterator<Integer> it;

public Integer poll() {
if (sharemap.size() > 0 && it!=null && it.hasNext()) {
Integer m = it.next();
it.remove();
return m;
} else {
return null;
}
}
}

Thread-0 add 10 elements! ShareMap size: 110

Thread-1 poll 110 elements! ShareMap size: 0

Read last : 0 ms shareMap : 0

可见ConcurrencyHashMap支持并发增加和删除,且最终读取的结果没有遗漏。

但并发删除就要慎重了!

有时会报IllegelState问题,通常是两个并发删除使用了同一个iterator,导致线程并发问题。

如下面这段代码:

package concurrencyTest;

import java.util.Iterator;
import java.util.concurrent.ConcurrentHashMap;

public class ConcurrencyTest3 {

/**
* @param args
*/
public static void main(String[] args) {
ConcurrentHashMap<Integer, Integer> map = new ConcurrentHashMap<Integer, Integer>() ;
for(int i=0;i<100 ; i++)
map.put(i, i+111111) ;

long start = System.currentTimeMillis() ;
Iterator<Integer> it = map.values().iterator();
Thread t1 = new Thread(new Consumer2(map,it)) ;
Thread t2 = new Thread(new Consumer2(map,it)) ;

t1.start();
t2.start();

try {
t1.join() ;
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Read last : " + (System.currentTimeMillis() - start) + " ms" + " shareMap : " + map.size());
}
}

class Consumer2 implements Runnable {
ConcurrentHashMap<Integer, Integer> sharemap ;
Iterator<Integer> it ;
int num = 0 ;

public Consumer2(ConcurrentHashMap<Integer, Integer> map, Iterator<Integer> iterator) {
sharemap = map ;
it = iterator ;
}

@Override
public void run() {
Integer i = poll();
while(i!=null) {
i = poll() ;
num++ ;
}
System.out.println(Thread.currentThread().getName() + " poll " + num + " elements! ShareMap size: " + sharemap.size() );
}

public Integer poll() {
if (sharemap.size() > 0 && it!=null && it.hasNext()) {
Integer m = it.next();
it.remove();
return m;
} else {
return null;
}
}
}

两个并发线程用一个iterator,直接报:
Exception in thread "Thread-0" Thread-1 poll 78 elements! ShareMap size: 1
java.lang.IllegalStateException
at java.util.concurrent.ConcurrentHashMap$HashIterator.remove(ConcurrentHashMap.java:1365)
at concurrencyTest.Consumer2.poll(ConcurrencyTest3.java:58)
at concurrencyTest.Consumer2.run(ConcurrencyTest3.java:48)
at java.lang.Thread.run(Thread.java:722)
Read last : 2 ms shareMap : 1


即使是使用两个各自的iterator线程,也是不安全的,因为可能造成重复读取,两边读到的数据量并不一致!

参考这篇文章: http://blog.csdn.net/cloudeagle_bupt/article/details/52643535 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: