`

hashmap多线程问题

 
阅读更多

hashmap多线程问题总结:

1、jdk1.8前存在多线程赋值死循环问题

2、所有jdk版本存在多线程赋值丢失数据问题

代码开路(具体原因分析不赘述,网络上很多自己去找):

package com.song.javabase;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Created by feng on 2019/9/6.
 */
public class HashMapDemo {

    public static void main(String[] args){
        //jdk1.8以下会引起部分线程死循环,多试几次,不是必现,jdk1.8解决了该问题
        testMyThread();

        //hashmap多线程hash冲突导致数据被覆盖,jdk1.8也有此问题
        //testMyThread1();

        //concurrenthashmap多线程解决MyThread1的问题
        //testMyThread2();
    }

    public static void testMyThread(){
        for(int i = 1; i <= 10; i++){
            new Thread(new MyThread(i)).start();
        }
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(MyThread.atomicInteger);
        System.out.println(MyThread.map.size());
    }

    public static void testMyThread1(){
        for(int i = 1; i <= 10; i++){
            new Thread(new MyThread1(i)).start();
        }
        try {
            new Thread().sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(MyThread1.map.size());
    }

    public static void testMyThread2(){
        for(int i = 1; i <= 10; i++){
            new Thread(new MyThread2(i)).start();
        }
        try {
            new Thread().sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(MyThread2.map.size());
    }
}

class MyThread implements Runnable{

    public static Map<Integer,Integer> map = new HashMap<Integer,Integer>(1);
    public static AtomicInteger atomicInteger = new AtomicInteger(0);

    private int id;

    public MyThread(int id){
        this.id = id;
    }

    @Override
    public void run() {
        for(int i = 0; i < 100000; i++) {
            //由于atomicInteger取值和加值不在一步操作,多线程下不但有数据跳过导致丢失,还可能产生同值hash碰撞,导致resize时hashmap死循环
            map.put(atomicInteger.get(), atomicInteger.get());
            atomicInteger.incrementAndGet();

            //即使atomicInteger取值和加值在一步操作,多线程下不会导致死循环,但是会有数据跳过导致丢失,atomic并不是万能的
            //int index = atomicInteger.getAndIncrement();
            //map.put(index, index);

            //同步代码块解决上述问题
            //synchronized (atomicInteger){
                //map.put(atomicInteger.get(), atomicInteger.get());
                //atomicInteger.incrementAndGet();
            //}
        }
        System.out.println(id + "结束");
    }
}

class MyThread1 implements Runnable{

    public static Map<Integer,Integer> map = new HashMap<Integer, Integer>(1);
    public int index;

    private int id;

    public MyThread1(int id){
        this.id = id;
        this.index = (id - 1) * 10000;
    }

    @Override
    public void run() {
        int count = 0;
        //index分区间线程不干扰,最终hashmap的大小不够10w,说明有hash冲突导致数据被覆盖。
        for(int i = 0; i < 10000; i++) {
            map.put(index , index);
            index ++;
            count ++;
        }
        System.out.println(id + "结束,总共" + count +"次");
    }
}

class MyThread2 implements Runnable{

    public static Map<Integer,Integer> map = new ConcurrentHashMap<Integer, Integer>(1);
    public int index;

    private int id;

    public MyThread2(int id){
        this.id = id;
        this.index = (id - 1) * 10000;
    }

    @Override
    public void run() {
        int count = 0;
        //index分区间多线程不干扰,改成concurrentHashMap,不存在hash冲突数据被覆盖的问题
        for(int i = 0; i < 10000; i++) {
            map.put(index , index);
            index ++;
            count ++;
        }
        System.out.println(id + "结束,总共" + count +"次");
    }
}

 

 

0
0
分享到:
评论

相关推荐

    关于如何解决HashMap线程安全问题的介绍

    4. 避免在多线程环境中直接使用HashMap:如果你确定不需要在多线程环境下共享HashMap,那么可以考虑局部变量的方式,只在单个线程中使用HashMap,这样就无需担心线程安全问题。 总结起来,理解HashMap的线程不安全...

    高级程序员必会的HashMap的线程安全问题,适用于0~2年的.7z

    然而,对于多线程环境,HashMap并不是线程安全的,这在并发编程中可能会引发一系列问题。本篇将深入探讨HashMap的线程安全问题,并提供相关的解决方案。 首先,我们需要了解HashMap在多线程环境下可能出现的问题: ...

    java的hashMap多线程并发情况下扩容产生的死锁问题解决.docx

    在Java的HashMap中,多线程并发环境下的扩容操作可能会引发死锁问题。这主要发生在JDK 1.7版本,因为其扩容机制采用了头插法。以下详细解释这个问题及其解决方案。 首先,HashMap的扩容机制是在容量达到阈值时触发...

    HashMap源码分析系列-第四弹:HashMap多线程解决方案.docx

    ### HashMap多线程解决方案 #### 一、引言 在多线程环境下,Java的`HashMap`类在处理并发操作时容易出现线程安全问题。本文档深入探讨了`HashMap`在多线程环境中可能遇到的安全问题,并提出了一系列可行的解决方案...

    通过代码证明HashMap是线程不安全的(只用了一个Java文件)

    这个主题通常涉及到多线程编程和Java集合框架的基础知识。本篇文章将通过分析`HashMap`的源码以及编写一个简单的测试程序来证明这一点。 首先,我们要理解什么是线程安全。线程安全是指在多线程环境中,一个类或...

    hashmap-thread-test:测试 Java HashMap 是否是线程安全的

    然而,`HashMap`并非线程安全,这意味着在多线程环境中直接使用`HashMap`可能会导致数据不一致、并发问题,甚至程序崩溃。本项目“hashmap-thread-test”显然是为了测试和展示这一特性。 ### Java HashMap 的特性 ...

    【并发】为什么HashMap是线程不安全的?

    目录 1.什么是线程安全性(what) 2.如何分辨一个类是否线程安全?(HOW) ...正确性:多个线程访问某个类,不管怎么调度这些线程,其代码中不需要额外的同步或协同(synchronized),这个类依然有正确

    hashmap面试题_hashmap_

    答:在多线程环境下,可以使用ConcurrentHashMap,它是线程安全的HashMap实现。 五、HashMap与HashSet的关系 HashSet基于HashMap实现,每个元素作为HashMap的一个键,值为null。因此,HashSet的操作性能也依赖于...

    Java多线程矩阵相乘的代码

    在Java编程语言中,多线程是实现并发执行任务的关键技术。这个压缩包中的内容,"Java多线程矩阵...通过对代码的阅读和分析,我们可以深入理解Java多线程在解决实际问题中的应用,同时也能掌握矩阵运算的并行化策略。

    Java多线程程序案例

    根据给定文件的信息,我们可以提炼出以下关于Java多线程程序设计的知识点: ### Java多线程基础 在Java中,多线程是通过`Thread`...掌握多线程编程不仅可以提升程序的性能,还能解决并发问题,使程序更加高效和稳定。

    多线程ATM取款机模拟

    多线程ATM取款机模拟 在 Java 中实现多线程 ATM 取款机模拟,涉及到多个关键技术点,如线程安全、同步机制、账户管理等。本文将详细解释标题、描述、标签和部分内容中的知识点。 1. 多线程编程 多线程编程是 Java...

    马士兵老师HashMap学习笔记

    为了避免这种情况,开发者需要在多线程环境下使用线程安全的数据结构,如ConcurrentHashMap,或者在单线程环境中确保put操作的原子性。 总的来说,马士兵老师的HashMap学习笔记不仅涵盖了HashMap的基础知识,还深入...

    HashMap底层原理.pdf

    而在JDK 1.8中,虽然在某些操作(如put操作)中增加了同步控制,但仍未从根本上解决多线程问题。如果需要线程安全的HashMap,推荐使用ConcurrentHashMap或者Collections.synchronizedMap。 总的来说,HashMap在单...

    05.HashMap相关面试题

    HashMap 在多线程环境下使用时,需要注意线程安全问题,否则可能会导致程序崩溃或数据不一致。 * 使用 ConcurrentHashMap 替代 HashMap,可以解决线程安全问题。 * 使用线程安全的集合框架,例如 ...

    HashMap类.rar

    5. **线程不安全**:HashMap不是线程安全的,如果在多线程环境中使用,需要外部同步机制,或者使用ConcurrentHashMap。 6. **null键与null值**:HashMap允许键和值为null,但只有一个键可以为null,且该键对应的值...

    java多线程编程(第二版)

    死锁是多线程编程中的一种常见问题,发生在两个或更多线程相互等待对方释放资源,从而导致所有线程都无法继续的情况。避免死锁的方法包括避免循环等待、设置超时、使用死锁检测算法等。 线程优先级也是Java多线程中...

    servlet线程安全问题

    Servlet/JSP 技术由于其多线程运行而具有很高的执行效率,但这也意味着需要非常细致地考虑多线程的安全性问题。 Servlet 的多线程机制是建立在 Java 多线程机制之上的。Servlet 容器会自动使用线程池等技术来支持...

    HashMap的数据结构

    4. **并发问题**:HashMap不是线程安全的,这意味着在多线程环境中,同时对HashMap进行读写操作可能会导致数据不一致。如果需要线程安全的哈希表,可以使用`ConcurrentHashMap`。 5. **null值**:HashMap允许键和值...

    HashMap与HashTable区别

    这意味着在多线程环境中,对`HashTable`的操作不会导致数据不一致的情况发生。 - **HashMap**: 默认是非线程安全的。如果多个线程同时访问一个`HashMap`实例,且至少有一个线程修改了该`HashMap`,则必须通过外部...

Global site tag (gtag.js) - Google Analytics