看这段代码
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
分享到:
相关推荐
### Oracle并发问题处理 #### 并发问题概述与重要性 在Oracle数据库中,随着企业级应用系统的扩展和用户数量的增长,多个用户并发访问同一份数据的现象变得越来越常见。如果数据库设计和应用程序开发中没有妥善...
Visual C++源代码 147 如何处理多用户更新数据并发问题Visual C++源代码 147 如何处理多用户更新数据并发问题Visual C++源代码 147 如何处理多用户更新数据并发问题Visual C++源代码 147 如何处理多用户更新数据并发...
在处理 Informix 并发问题时,核心关注的是如何确保数据一致性并提高系统效率。并发问题通常发生在多个用户或进程同时访问和修改同一数据时,可能导致数据不一致或死锁。在 Informix 数据库管理系统中,有多种策略...
然而,当需要发送多个Ajax请求时,可能会出现并发问题,导致数据处理混乱或者请求响应顺序不可控。本文将深入探讨这个问题,并提供解决方案。 一、并发问题的来源 1. 请求队列:浏览器为了防止过多并发请求导致...
在编程领域,尤其是在开发多用户在线应用时,处理多用户更新数据并发问题是一个至关重要的环节。这涉及到数据库的事务管理、锁机制、并发控制策略等多个方面。本实例以C++.NET为开发环境,通过源代码的方式,展示了...
这几天在研究服务器的并发性能,当服务的方法需要执行长时间的任务时,发现WCF宿主到Console程序,... 最后问题已经解决了,参考资源中的文件:关于WCF 自我寄宿(Self-Hosting) 执行长时间任务并发问题_解决及源码.doc
Impala 并发查询缓慢问题解决方案 Impala 是一个基于Apache Hadoop的高性能、实时查询引擎,但是在并发查询时,可能会出现缓慢问题。本文将提供三种改造方案来解决Impala并发查询缓慢问题,并对每种方案进行测试...
在本文中,我们将深入探讨如何使用C#中的队列数据结构(Queue)来解决简单的并发问题。队列是一种线性数据结构,遵循先进先出(FIFO)的原则,即第一个进入的元素也将是第一个离开的元素。这种特性使得队列在处理...
在探讨"pgsql的并发问题"时,我们深入研究了PostgreSQL如何处理并发操作以及如何确保在不影响性能的情况下,应用程序查询能够获得正确的结果。这涉及到的关键概念包括多版本并发控制(MVCC)、两阶段锁定(2PL)以及...
本文实例讲述了C#解决SQlite并发异常问题的方法。分享给大家供大家参考,具体如下: 使用C#访问sqlite时,常会遇到多线程并发导致SQLITE数据库损坏的问题。 SQLite是文件级别的数据库,其锁也是文件级别的:多个线程...
10. **并发模式**:书中可能还会介绍生产者消费者模式、读写锁模式、双端队列模式等经典的并发设计模式,帮助开发者解决实际问题。 通过学习《Java并发编程实战》的源码,你可以更直观地了解这些概念如何在实际代码...
《Java并发编程实战》这本书是关于Java语言中并发编程技术的经典著作。它详细介绍了如何在Java环境中有效地实现多线程程序和并发控制机制。在Java平台上,由于其本身提供了强大的并发编程支持,因此,掌握并发编程...
提高 IIS 的并发访问量达到十万的并发 IIS(Internet Information Services)是微软推出的 Web 服务器,性能较之前有很大的提升。但是,IIS 的默认设置并不适合高并发的请求。为了提高 IIS 的并发访问量,达到十万...
11. **分布式并发**:简述在分布式系统中的并发问题,如分布式锁、分布式协调服务(如Zookeeper)以及微服务架构下的并发考量。 这本书是Java开发者提升并发编程能力的宝贵资源,适合有一定Java基础并希望在并发...
【帆软7.0.4并发补丁】是一款针对帆软报表软件FineReport 7.0.4版本的优化工具,其主要目的是解决在多用户同时访问时可能出现的并发访问限制问题。在企业环境中,特别是在大数据量处理和高并发访问的情况下,系统的...
首先,"Java线程并发面试题87.pdf"很可能包含了87个关于Java并发的常见面试问题,这些问题涵盖了线程基础知识、同步机制、线程池、死锁避免与解决、并发集合类的使用等多个方面。例如,可能会讨论Java中如何实现线程...
带你掌握多线程并发编程(线程安全,线程调度,线程封闭,同步容器等)与高并发处理思路与手段(扩容,缓存,队列,拆分等),构建完整的并发与高并发知识体系,胜任实际开发中并发与高并发问题的处理,倍增高薪面试...
综上所述,《Java并发实战》这本书是从理论和实践两个维度来讲解Java并发编程,强调了对并发场景的分析和解决问题的实践能力,帮助读者克服学习并发编程时的难点。通过这本书,读者可以逐步建立起对并发编程的全面...
然而,尽管Go语言提供了一套新的并发原语和机制,例如goroutines、channels、select语句等,但并发问题仍然存在,并且这些问题常常难以调试和发现。因此,对Go语言中并发Bug的研究显得尤为重要。 为了深入探讨Go...