昨天在开发者头条上面看的一篇文章针对Map相关的线程安全讲解说的很好,今天根据思路还原了场景(隔壁老王半夜为何尖叫?这例子说的有点让老王很忙)。
Java代码:
package com.boonya.concurrent;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
* @author PJL
* @note 功能描述:Add值的多线程安全问题--最优解方式是ConcurrentHashMap+Atomic*级别的原子操作
* @package com.boonya.concurrent
* @filename AddConcurrent.java
* @date 2019年4月23日 下午1:36:42
public class AddConcurrent {
* HashMap非线程安全
* @throws InterruptedException
public static void test0() throws InterruptedException{
HashMap<String, Integer> map = new HashMap<String,Integer>();
Integer integer = new Integer(1);
map.put("key", integer);
ExecutorService executorService = Executors.newFixedThreadPool(100);
for (int i = 0; i < 1000; i++) {
executorService.execute(new Runnable() {
@Override
public void run() {
map.put("key", map.get("key").intValue()+1) ;
Thread.sleep(3000); //模拟等待执行结束
System.out.println("test0()------" + map.get("key") + "------");
executorService.shutdown();
* 严格线程安全的同步非原子操作--非线程安全
* @throws InterruptedException
public static void test1() throws InterruptedException{
Hashtable<String, Integer> map = new Hashtable<String,Integer>();
Integer integer = new Integer(1);
map.put("key", integer);
ExecutorService executorService = Executors.newFixedThreadPool(100);
for (int i = 0; i < 1000; i++) {
executorService.execute(new Runnable() {
@Override
public void run() {
map.put("key", map.get("key").intValue()+1) ;
Thread.sleep(3000); //模拟等待执行结束
System.out.println("test1()------" + map.get("key") + "------");
executorService.shutdown();
* 线程安全的非原子操作--非线程安全
* @throws InterruptedException
public static void test2() throws InterruptedException{
ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<String,Integer>();
Integer integer = new Integer(1);
map.put("key", integer);
ExecutorService executorService = Executors.newFixedThreadPool(100);
for (int i = 0; i < 1000; i++) {
executorService.execute(new Runnable() {
@Override
public void run() {
map.put("key", map.get("key").intValue()+1) ;
Thread.sleep(3000); //模拟等待执行结束
System.out.println("test2()------" + map.get("key") + "------");
executorService.shutdown();
* 线程安全的原子操作--线程安全
* @throws InterruptedException
public static void test3() throws InterruptedException{
ConcurrentHashMap<String, AtomicInteger> map = new ConcurrentHashMap<String,AtomicInteger>();
AtomicInteger integer = new AtomicInteger(1);
map.put("key", integer);
ExecutorService executorService = Executors.newFixedThreadPool(100);
for (int i = 0; i < 1000; i++) {
executorService.execute(new Runnable() {
@Override
public void run() {
map.get("key").incrementAndGet();
Thread.sleep(3000); //模拟等待执行结束
System.out.println("test3()------" + map.get("key") + "------");
executorService.shutdown();
public static void main(String[] args) throws InterruptedException {
AddConcurrent.test0();
AddConcurrent.test1();
AddConcurrent.test2();
AddConcurrent.test3();
输出结果:
test0()------998------
test1()------998------
test2()------413------
test3()------1001------
这个核心思想就是线程安全的原子操作一定是线程安全的。
方式1. 使用Hashtable
其实现原理是在增删改查的方法上使用了synchronized锁机制,在多线程环境下,无论是读数据,还是修改数据,在同一时刻只能有一个线程在执行synchronize方法,因为是对整个表进行锁定。所以线程越多,对该map的竞争越激烈,效率越低,不推荐使用。
方式2. 使用Collections.synchronizedMap(new Hash...
APP打开
@Override
public void run() {
System.out.println("Before Java8, too much code for too l...
APP打开
谈谈HashMap线程不安全的体现HashMap的原理以及如何实现,之前在JDK7与JDK8中HashMap的实现中已经说明了。那么,为什么说HashMap是线程不安全的呢?它在多线程环境下,会发生什么情况呢?3个情况,1个put会同时扩容早造成死循环,2.2个put引发扩容,另外的线程有可能get不到。3.有可能2个同时put,导致1个丢失,被后1个put给覆盖掉了。 一种情况是...
APP打开
import java.util.Scanner; import java.util.Map; import java.util.HashMap; public class Test { //pri
APP打开
已经得到值,现在需要判断: Q290010101 1 Q290060101 1 Q290060501 1 Q290010101 2 将Q290010101的值相加,也就是 Q290010101 3 Q
APP打开
在我不知道Key的名称的情况下,不管Map中值的类型,将Value全部以String类型相加到一起,结果应该是好长的一串 这种方法能不能实现 因为list有get(int),而map中的get参数就得
APP打开
public void test() {
List<Person> people = new ArrayList<>();
people.add(new Person("zhangsan",20...
APP打开
直接上代码,可直接运行:
public static void main(String[] args) {
List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
Map<String, Object> map1 = ne...
APP打开