关于ConcurrencyHashmap的并发问题
2016-09-25 00:21
746 查看
看这段代码
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
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
相关文章推荐
- 关于freemarker里面的hashmap使用问题
- 关于hashmap的遍历问题
- 关于openfire并发登录的问题
- Java中关于HashMap的元素遍历的顺序问题
- 关于ASIHTTPRequest连续请求,并发连续,间隔时间很小崩溃问题
- 关于并发的时候,出现的问题以及解决的方法
- 关于流水帐表序列号生成时的并发操作问题
- 关于采用HashMap作为本地缓存遇到的问题
- 并发场景下HashMap死循环导致CPU100%的问题
- 关于HBase0.94版本在split region后META Scanner和CatalogJanitor并发操作时存在的问题
- 关于hashmap的遍历问题
- 关于freemarker里面的hashmap使用问题
- 关于并发用户与集合点的问题
- 关于线程和线程并发的一些问题
- 解决关于多客户端操作数据库并发问题
- 关于freemarker里面的hashmap使用问题
- 关于c/s vs web 程序的并发问题
- 关于map的数据排序问题(hashmap,treemap)
- 高并发下的HashMap问题
- 关于ASP.Net应用程序的高性能和多并发问题讨论