众所周知hashMap 是线程不安全的,在多线程访问的情况下,要做同步的处理
ConcurrentHashMap是Java 5中支持高并发、高吞吐量的线程安全HashMap实现
ConcurrentHashMap get() 总能拿到最新的值,类似于关键字 volatile保证100%读取到最新的数据
如下用代码说明:
package com.iteye.javaso.demo;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class CopyOfConCurrentHashMapThreadTest2 {
ConcurrentHashMap<String, String> map = new ConcurrentHashMap<String, String>();
public static void main(String args[]) {
CopyOfConCurrentHashMapThreadTest2 test = new CopyOfConCurrentHashMapThreadTest2();
Runnable sleep = new ThreadSleep2(test, "第一条线程");
ThreadSecond2 charge2 = new ThreadSecond2(test, "改变值的第2线程");
ThreadSecond2 charge3 = new ThreadSecond2(test, "改变值的第3线程");
ThreadSecond2 charge4 = new ThreadSecond2(test, "改变值的第4线程");
ThreadSecond23 chargeXX = new ThreadSecond23(test, "改变值的XXXX线程");
ExecutorService exc = Executors.newFixedThreadPool(5);
exc.execute(sleep);
exc.execute(charge3);
exc.execute(charge2);
exc.execute(chargeXX);
exc.execute(charge4);
exc.shutdown();
System.out.println("洗洗睡吧----------------");
try {
Thread.sleep(16000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("多个线程后,最终运行结果:" + test.map.get("firstKey"));
}
public void put(String value, int state) {
map.put("firstKey", value);
// Thread thread= Thread.currentThread();
if (state == 0) {
System.out.println("开始睡觉了--------------");
try {
Thread.sleep(4000);
System.out.println("睡醒了-------");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
class ThreadSleep2 extends Thread {
ConcurrentHashMap<String, String> map;
public ThreadSleep2(ConcurrentHashMap<String, String> map, String threadName) {
this.map = map;
this.name = threadName;
}
CopyOfConCurrentHashMapThreadTest2 test;
public ThreadSleep2(CopyOfConCurrentHashMapThreadTest2 test,
String threadName) {
super(threadName);
this.test = test;
this.name = threadName;
}
@Override
public void run() {
Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
System.out.println("---------------进入第一条线程-----睡十秒先--------");
System.out.println("第一条线程未设置前值为:*** " + test.map.get("firstKey"));
test.put(name, 0);
System.out.println("第一条线程执行完毕 Map中值为:" +test.map.get("firstKey"));
}
String name = "";
public String toString() {
return "当前线程的名字是:" + name;
}
}
class ThreadSecond2 extends Thread {
ConcurrentHashMap<String, String> map;
public ThreadSecond2(ConcurrentHashMap<String, String> map,
String threadName) {
super(threadName);
this.map = map;
this.name = threadName;
}
CopyOfConCurrentHashMapThreadTest2 test;
public ThreadSecond2(CopyOfConCurrentHashMapThreadTest2 test,
String threadName) {
super(threadName);
this.test = test;
this.name = threadName;
}
@Override
public void run() {
System.out.println("-----------进入其它线程---------");
System.out.println("当前线程是:" + this.name + " 未设置map前值为:"
+ test.map.get("firstKey"));
test.put(name, 2);
System.out.println("hashMap中 firstKey值为:" + name);
}
String name = "";
public String toString() {
return "当前线程的名字是:" + name;
}
}
class ThreadSecond23 extends Thread {
ConcurrentHashMap<String, String> map;
public ThreadSecond23(ConcurrentHashMap<String, String> map,
String threadName) {
super(threadName);
this.map = map;
this.name = threadName;
}
CopyOfConCurrentHashMapThreadTest2 test;
public ThreadSecond23(CopyOfConCurrentHashMapThreadTest2 test,
String threadName) {
super(threadName);
this.test = test;
this.name = threadName;
}
@Override
public void run() {
System.out.println("-----------进入XXXXXXX线程---------");
System.out.println("当前线程是:" + Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
test.put(name, 2);
System.out.println("hashMap中 firstKey值为:" + name);
}
String name = "";
public String toString() {
return "当前线程的名字是:" + name;
}
}
---------------进入第一条线程-----睡十秒先--------
-----------进入其它线程---------
第一条线程未设置前值为:*** null
当前线程是:改变值的第2线程 未设置map前值为:null
hashMap中 firstKey值为:改变值的第2线程
洗洗睡吧----------------
开始睡觉了--------------
-----------进入其它线程---------
-----------进入其它线程---------
当前线程是:改变值的第4线程 未设置map前值为:改变值的第2线程
-----------进入XXXXXXX线程---------
当前线程是:pool-1-thread-4
当前线程是:改变值的第3线程 未设置map前值为:改变值的第2线程
hashMap中 firstKey值为:改变值的第3线程
hashMap中 firstKey值为:改变值的第4线程
hashMap中 firstKey值为:改变值的XXXX线程
睡醒了-------
第一条线程执行完毕 Map中值为:改变值的XXXX线程
多个线程后,最终运行结果:改变值的XXXX线程
最高优先级的线程:ThreadSleep2 put 值后,进入睡眠,由于未进行同步处理,这时其它线程开始执行,改变了map中firstKey值,到最先执行的线程醒来后,输出map中firstKey值已被其它线程改变:改变值的XXXX线程, 可见get() 总能拿到最新的值,类似于关键字 volatile保证100%读取到最新的数据.
对put方法,进行同步后:
public synchronized void put(String value, int state) {
map.put("firstKey", value);
// Thread thread= Thread.currentThread();
if (state == 0) {
System.out.println("开始睡觉了--------------");
try {
Thread.sleep(4000);
System.out.println("睡醒了-------");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
synchronized (test) {
test.put(name, 0);
System.out.println("第一条线程执行完毕 Map中值为:" +test.map.get("firstKey"));
}
输出:
---------------进入第一条线程-----睡十秒先--------
第一条线程未设置前值为:*** null
开始睡觉了--------------
洗洗睡吧----------------
-----------进入其它线程---------
-----------进入其它线程---------
当前线程是:改变值的第3线程 未设置map前值为:第一条线程
当前线程是:改变值的第2线程 未设置map前值为:第一条线程
-----------进入XXXXXXX线程---------
当前线程是:pool-1-thread-4
-----------进入其它线程---------
当前线程是:改变值的第4线程 未设置map前值为:第一条线程
睡醒了-------
第一条线程执行完毕 Map中值为:第一条线程
hashMap中 firstKey值为:改变值的XXXX线程
hashMap中 firstKey值为:改变值的第2线程
hashMap中 firstKey值为:改变值的第3线程
hashMap中 firstKey值为:改变值的第4线程
多个线程后,最终运行结果:改变值的第3线程
其它线程要等待sleep线程释放锁,至第一条线程执行完毕时,map值为:sleep线程 put的值:第一条线程
结论ConcurrentHashMap put操作需要做同步,get操作不需要
分享到:
相关推荐
Java提供了多种线程安全的集合,如`ConcurrentHashMap`、`AtomicInteger`等,它们在多线程环境下能够保证数据的一致性和完整性。线程可以在执行过程中将计算结果放入这些线程安全的数据结构,而无需担心数据竞争的...
8. **并发集合类**:Java提供了并发安全的集合类,如`ConcurrentHashMap`, `CopyOnWriteArrayList`, `BlockingQueue`等,它们内部实现了线程安全的算法,可以在多线程环境下高效使用。 9. **线程中断**:`interrupt...
Java提供了一些线程安全的集合类,如ConcurrentHashMap、CopyOnWriteArrayList和CopyOnWriteArraySet,它们在多线程环境下提供了高并发的访问性能。 九、死锁检测与避免 死锁是多线程编程中的常见问题,两个或多个...
在Java编程领域,多线程是面试中常见且重要的知识点,尤其对于系统设计和高并发处理的岗位至关重要。本文将围绕“多线程面试题”这一主题,深入探讨相关概念、技术及其应用。 1. **线程的概念**:线程是程序执行的...
《Java多线程编程实战指南》这本书深入浅出地讲解了Java多线程的核心概念和实战技巧,分为核心篇和设计模式篇,旨在帮助开发者掌握并应用多线程技术。 1. **线程基础** - **线程的创建**:Java提供了两种创建线程...
在Java编程领域,多线程是一项至关重要的技术,它允许程序同时执行多个任务,从而提高系统资源的利用率和程序的响应速度。这份“JAVA多线程编程技术PDF”是学习和掌握这一领域的经典资料,涵盖了多线程的全部知识点...
【并发容器的线程安全性】与`HashMap`不同,`ConcurrentHashMap`通过采用非阻塞算法(如CAS操作)和分段锁机制来保证并发性能,避免了整个表的锁定,提高了在多线程环境下的并发性和性能。 【存储结构】`...
在IT领域,多线程和高并发是两个关键概念,特别是在Java编程中,它们对于构建高效、可扩展的系统至关重要。下面将详细解释这两个概念及其在Java中的实现和应用。 多线程是指在一个应用程序中同时运行多个独立的执行...
Java提供了一系列并发容器,如ConcurrentHashMap、CopyOnWriteArrayList等,它们内部实现了线程安全,能够在多线程环境下高效地使用。 八、死锁 当两个或更多线程互相等待对方释放资源而无法继续执行时,就会发生...
在Java编程语言中,多线程是实现并发执行任务的关键技术。这个压缩包中的内容,"Java多线程矩阵相乘的代码",显然提供了一个示例,演示如何利用多线程来加速矩阵乘法这一计算密集型操作。矩阵相乘在科学计算、图像...
本项目“poi多线程大数据导出excel文件”提供了一个解决方案,利用多线程来提高Excel的大数据导出效率。 Apache POI 3.1版本是较早的版本,而项目中使用了更新的4.1版本,这意味着它可能利用了更多优化和新特性。在...
9. **线程安全的数据结构**:某些数据结构(如Java的ConcurrentHashMap)设计为线程安全,可以在多线程环境下直接使用,无需额外的同步措施。 10. **线程局部存储**:线程局部变量只对创建它的线程可见,这样可以在...
在Java编程语言中,多线程是实现并发执行任务的关键技术。这个“java多线程控制的赛跑程序”是一个示例,展示了如何利用多线程来模拟一场赛跑比赛。在这个程序中,每个参赛者(线程)都有自己的运行逻辑,通过线程的...
在IT领域,多线程是程序设计中的一个重要概念,尤其在服务器端开发、实时系统以及高性能计算中扮演着核心角色。多线程允许一个应用程序同时执行多个不同的任务,提高资源利用率,实现高效的并发处理。本压缩包“多...
Java多线程编程是Java开发中的重要组成部分,它允许程序同时执行多个任务,极大地提高了程序的效率和响应性。在现代计算机系统中,多线程技术尤其关键,因为它们能够充分利用多核处理器的能力。这份"Java多线程编程...
这个方法确保在多线程环境下安全地创建哈希表。在源码中,`sizeCtl`变量扮演着关键角色,它的值有多种含义: 1. `-1`表示有一个线程正在创建哈希表。 2. `-N`表示有`N-1`个线程正在进行表复制(扩容时发生)。 3. ...
"多线程.pdf"很可能包含更详细的理论解释和案例分析,可能涵盖了线程优先级、线程生命周期(新建、就绪、运行、阻塞、死亡)、线程安全的数据结构(如ConcurrentHashMap)以及高级特性如线程局部变量(ThreadLocal)...
在Java编程中,多线程设计是实现高效并发处理的关键技术。它允许程序中的多个执行单元(线程)同时运行,提高系统资源利用率并优化性能。本知识点将深入探讨Java多线程设计以及如何利用“不可变对象”(immutable ...
Java的并发集合库(java.util.concurrent包)提供了线程安全的集合类,如ConcurrentHashMap、CopyOnWriteArrayList和ConcurrentLinkedQueue等,它们在多线程环境下能确保数据的一致性和安全性。 十、异常处理 在多...