1、线程不安全的HashMap
因为多线程环境下,使用Hashmap进行put操作会引起死循环,导致CPU利用率接近100%,所以在并发情况下不能使用HashMap。

2、效率低下的HashTable容器
HashTable容器使用synchronized来保证线程安全,但在线程竞争激烈的情况下HashTable的效率非常低下。因为当一个线程访问HashTable的同步方法时,其他线程访问HashTable的同步方法时,可能会进入阻塞或轮询状态。如线程1使用put进行添加元素,线程2不但不能使用put方法添加元素,并且也不能使用get方法来获取元素,所以竞争越激烈效率越低。

3、ConcurrentHashMap分段锁技术
ConcurrentHashMap是Java 5中支持高并发、高吞吐量的线程安全HashMap实现。

我们以ConcurrentHashMap来说一下分段锁的含义以及设计思想,ConcurrentHashMap中的分段锁称为Segment,类似于HashMap(JDK7与JDK8中HashMap的实现)的结构,即内部拥有一个Entry数组,数组中的每个元素又是一个链表;同时又是一个ReentrantLock(Segment继承了ReentrantLock)。

当需要put元素的时候,并不是对整个hashmap进行加锁,而是先通过hashcode来知道他要放在哪一个分段中,然后对这个分段进行加锁,所以当多线程put的时候,只要不是放在一个分段中,就实现了真正的并行的插入。

但是,在统计size的时候,可就是获取hashmap全局信息的时候,就需要获取所有的分段锁才能统计。

分段锁的设计目的是细化锁的粒度,当操作不需要更新整个数组的时候,就仅仅针对数组中的一项进行加锁操作。

4、用法
模拟信息的发送和接收,场景是这样的:
服务器向客户端发送信息,要保证信息100%的发送给客户端,那么发给客户端之后,客户端返回一个消息告诉服务器,已经收到。当服务器一直没有收到客户端返回的消息,那么服务器会一直发送这个信息,直到客户端接收并确认该信息,这时候再删除重复发送的这个信息。

为了模拟该场景,这里写两个线程,一个是发送线程,一个是接收线程,把要发送的信息保存到线程安全的对象里面,防止发生线程安全问题,这里采用ConcurrentHashMap。

a、SendThread:信息重新发送类

package com.lynch.lock;

import java.util.Map.Entry;

/**
*
*
* @author Lynch
*/
public class SendThread extends Thread {
@Override
public void run() {
try {
sleep(6000);
while (ConcurrentHashMapTest.pushMessage.size() > 0) {
for (Entry<Integer, String> hashMap : ConcurrentHashMapTest.pushMessage.entrySet()) {
System.out.println("消息id:" + hashMap.getKey()+ "未发送成功,在此重发:" + hashMap.getValue());
} sleep(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

b、ReceiveThread:信息接收类

package com.lynch.lock;

import java.util.Map.Entry;

/**
* 接收发送过来的信息,并从内存中删除
*
* @author Administrator
*
*/
public class ReceiveThread extends Thread {
@Override
public void run() {
try {
for (int i = 0; i < 100000; i++) {
sleep(2000);
for (Entry<Integer, String> map : ConcurrentHashMapTest.pushMessage.entrySet()) {
if (map.getKey() == i) {
System.out.println("成功收到id为:" + map.getKey() + "返回的信息,删除该元素");
ConcurrentHashMapTest.pushMessage.remove(map.getKey());
}
}
System.out.println("内存对象中的元素数量为:" + ConcurrentHashMapTest.pushMessage.size());
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

c、ConcurrentHashMapTest:主类入口

package com.lynch.lock;

import java.util.concurrent.ConcurrentHashMap;

/**
* 模拟信息的发送和接收
*
* @author Lynch
*/
public class ConcurrentHashMapTest {
public static ConcurrentHashMap<Integer, String> pushMessage = new ConcurrentHashMap<Integer, String>(); public static void main(String[] args) {
for (int i = 0; i < 5; i++) {
pushMessage.put(i, "该消息是id为" + i + "的消息");
} Thread sendThread = new SendThread();
Thread receiveThread = new ReceiveThread();
sendThread.start();
receiveThread.start();
for (int i = 5; i < 10; i++) {
pushMessage.put(i, "该消息是id为" + i + "的消息");
}
}
}

这样两个线程可以轮流的进行各自的事情,并且不会造成数据安全的问题。用这种方式,再结合Androidpn的推送机制,会更加符合实际生产中的应用。

ConcurrentHashMap--锁的分段技术的更多相关文章

  1. Java:ConcurrentHashMap的锁分段技术

    术语定义 术语 英文 解释 哈希算法 hash algorithm 是一种将任意内容的输入转换成相同长度输出的加密方式,其输出被称为哈希值.  哈希表 hash table 根据设定的哈希函数H(ke ...

  2. ConcurrentHashMap(锁分段技术)

    线程不安全的HashMap     因为多线程环境下,使用Hashmap进行put操作会引起死循环,导致CPU利用率接近100%,所以在并发情况下不能使用HashMap.   效率低下的HashTab ...

  3. java多线程 -- ConcurrentHashMap 锁分段 机制

    hashtable效率低ConcurrentHashMap 线程安全,效率高 Java 5.0 在 java.util.concurrent 包中提供了多种并发容器类来改进同步容器 的性能. Conc ...

  4. Java 中15种锁的介绍:公平锁,可重入锁,独享锁,互斥锁,乐观锁,分段锁,自旋锁等等

    Java 中15种锁的介绍 Java 中15种锁的介绍:公平锁,可重入锁,独享锁,互斥锁,乐观锁,分段锁,自旋锁等等,在读很多并发文章中,会提及各种各样锁如公平锁,乐观锁等等,这篇文章介绍各种锁的分类 ...

  5. 3.ConcurrentHashMap 锁分段机制 Copy-On-Write

    /*ConcurrentHashMap*/ Java 5.0 在 java.util.concurrent 包中提供了 多种 并发容器来改进同步容器的性能 ConcurrentHashMap 同步容器 ...

  6. java8的ConcurrentHashMap为何放弃分段锁,为什么要使用CAS+Synchronized取代Segment+ReentrantLock

    原文地址:https://cloud.tencent.com/developer/article/1509556 推荐一篇 ConcurrentHashMap 和 HashMap 写的比较的的文章 j ...

  7. 四、ConcurrentHashMap 锁分段机制

    回顾: HashMap与Hashtable的底层都是哈希表,但是 HashMap:线程不安全 Hashtable:线程安全,但是效率非常低,且存在[复合操作](如"若存在则删除") ...

  8. redis分布式锁扣减库存弊端: 吞吐量低, 解决方法:使用 分段锁 分布式分段锁并发扣减库存--代码实现

    package tech.codestory.zookeeper.aalvcai.ConcurrentHashMapLock; import lombok.AllArgsConstructor; im ...

  9. 关于分布式锁Java常用技术方案

    前言:       由于在平时的工作中,线上服务器是分布式多台部署的,经常会面临解决分布式场景下数据一致性的问题,那么就要利用分布式锁来解决这些问题.      所以自己结合实际工作中的一些经验和网上 ...

随机推荐

  1. android 学习(1)

    第二次发生这种事了,写完啦,手一抖,丢了,这个写完不用博客园了,怪不得用户越来越少 简写 androidstudio安装注意点 1JDK安装需配置环境变量 2安装遇到haxm错误需要进入BIOS打开C ...

  2. spark hive 结合处理 把多行变成多列

    原数据格式 : gid       id      score a1        1       90 a1        2      80 a1       3      79 a1       ...

  3. Eclipse PHP Studio(EPP)

    Eclipse PHP Studio (EPP) 中文版官方网站 :http://epp.php100.com/ EclipsePHP Studio 简体中文版介绍 - EPP EclipsePHP ...

  4. 记一次 Ubuntu 使用 arptables 抵御局域网 ARP 攻击

    . . . . . 前段时间大概有一个月左右,租房的网络每天都断一次,每次断大概一两分钟左右就恢复了,所以没太在意.直到有一天晚上,LZ 正在写博客,但是网络频繁中断又重新连上再中断.待 LZ 好不容 ...

  5. mysql处理字符串

    1.从左开始截取字符串 left(str, length) 说明:left(被截取字段,截取长度) 例:select left(content,200) as abstract from my_con ...

  6. WINDOWS的NTP配置

    将下面内容复制到记事本,保存成ntp.bat net stop w32Time REG ADD HKLM\SYSTEM\CurrentControlSet\Services\W32Time\TimeP ...

  7. java基础(1)-比较jdk5,jdk6,jdk7的新特性

    jdk8已经出来好长时间了,这里自己学习时简单总结的jdk5,jdk6和jdk7的新特性:本文提纲: 一.jdk5的新特性 二.jdk6的新特性 三.jdk7的新特性 一.jdk5的新特性 首先简单介 ...

  8. Log4j基本用法----日志级别

    基本使用方法: Log4j由三个重要的组件构成:日志信息的优先级,日志信息的输出目的地,日志信息的输出格式.日志信息的优先级从高到低有ERROR.WARN.INFO.DEBUG,分别用来指定这条日志信 ...

  9. yii2.0 Cache缓存

    1.控制器中CacheDemoController.php 1 <?php 2 /** 3 * Created by PhpStorm. 4 * User: liangzi 5 * Date: ...

  10. 未能加载文件或程序集“ICSharpCode.SharpZipLib, Version=0.86.0.518, Culture=n

    这个可能是因为,缺少文件ICSharpCode.SharpZipLib.dll文件. 我从网上下载了个dll文件,放到根目录中自己好了.