看这段代码
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
分享到:
相关推荐
Visual C++源代码 147 如何处理多用户更新数据并发问题Visual C++源代码 147 如何处理多用户更新数据并发问题Visual C++源代码 147 如何处理多用户更新数据并发问题Visual C++源代码 147 如何处理多用户更新数据并发...
关于处理informix并发问题的几点心得,通过实例来描述在编写ec程序过程中,如何解决并发问题的经验和技巧.
Oracle并发问题处理Oracle并发问题处理
该示例解决了发送多个Ajax请求时引起的并发问题
这几天在研究服务器的并发性能,当服务的方法需要执行长时间的任务时,发现WCF宿主到Console程序,... 最后问题已经解决了,参考资源中的文件:关于WCF 自我寄宿(Self-Hosting) 执行长时间任务并发问题_解决及源码.doc
并发问题详述 并发问题详述 并发问题详述 并发问题详述 并发问题详述
使用TimeStamp控制并发问题示例,主要内容是在数据库中怎样防上两个以上用户同时使用数据而产生的并发操作
本文实例讲述了C#解决SQlite并发异常问题的方法。分享给大家供大家参考,具体如下: 使用C#访问sqlite时,常会遇到多线程并发导致SQLITE数据库损坏的问题。 SQLite是文件级别的数据库,其锁也是文件级别的:多个线程...
MySQL Innodb锁解决并发问题
pgsql的并发问题。 MVCC,2PL,封锁。
高并发场景下,如何解决数据库与缓存双写的时候数据不一致的情况?如何解决大value缓存的全量更新效率低下问题?
处理多用户更新数据并发问题 编程小实例,C++.net源代码编写
带你掌握多线程并发编程(线程安全,线程调度,线程封闭,同步容器等)与高并发处理思路与手段(扩容,缓存,队列,拆分等),构建完整的并发与高并发知识体系,胜任实际开发中并发与高并发问题的处理,倍增高薪面试...
Impala并发查询缓慢问题解决方案.docx
05、CAS详解和学透面试必问并发安全问题_ev05、CAS详解和学透面试必问并发安全问题_ev05、CAS详解和学透面试必问并发安全问题_ev05、CAS详解和学透面试必问并发安全问题_ev05、CAS详解和学透面试必问并发安全问题_ev...
本文的主题是关于具有java语言风格的Thread、synchronized、volatile,以及J2SE5中新增的概念,如锁(Lock)、原子性(Atomics)、并发集合类、线程协作摘要、Executors。开发者通过这些基础的接口可以构建高并发、线程...
千万级规模高性能、高并发的网络架构经验分享;亿级流量网站架构核心技术,并发编程经典实例
因为以前没有关于 Go 的并发 Bugs 的研究。 所以, 到目前为止,还不清楚 Go 的这些并发机制是否真的比传统语言更容易适用千并发编程, 更不容易出错。 本文在开源社区 GitHub上选取了六个开源的并且用于实际生产...
关于c#处理并发的小demo,利用lock处理,喜欢的可以看看
关于数据库并发控制,该PPT主要以高等教育数据库系统概论为基础,介绍了锁的使用