JUC中创建的组件 多线程使用“哈希表”

JUC中创建的组件

JUC中创建的组件这些内容都不太常用,偶尔用到面试的时候,偶尔用到!到时候自行查找即可,本文主要来快速的过一下,留个印象即可~

JUC(java.util.concurrent)和多线程相关的工具类。

1.Callable的用法

非常类似于Runnable(描述了一个任务/一个线程要干啥),Runnable通过run方法描述,返回类型void,但是很多时候,是希望任务要有返回值的,有一个具体的结果产出的!!

call的方法有返回值

写一个代码,创建一个线程,用这个线程计算一下:1+2+3+4+……+1000

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;public class Main {public static void main(String[] args) throws ExecutionException,InterruptedException {//这只是创建个任务Callable<Integer> callable=new Callable<Integer>() {@Overridepublic Integer call() throws Exception {//Integer 看返回值类型(看实际需要)int sum=0;for (int i = 1; i <= 1000; i++) {sum=sum+i;}return sum;}};//还需要找个人,来完成这个任务(线程)//Thread不能直接传Callable,需要在包装一层FutureTask<Integer> futureTask=new FutureTask<>(callable);Thread t=new Thread(futureTask);t.start();//取结果System.out.println(futureTask.get());}
}

上述代码的运行结果为:

那么在上述代码中:如何保证调用get()的时候,t线程的call方法是执行完毕了呢??

其实get()和join()类似,都是会阻塞等待~

那么,到目前为止:我们有着以下四种方法来创建线程~

  • 继承 Thread
  • 实现Runnable
  • 基于lambda
  • 实现Callable

ReentrantLock的可重入:

synchronized关键字是基于代码块的方法来控制加锁解锁的!

ReentrantLock则是提供了lock和unlock两个独立的方法来进行加锁解锁的,虽然大部分情况下,使用synchronized就足够了,ReentrantLock也是一个重要的补充

体现在三个方面:

  1. synchronized只是加锁解锁,加锁的时候,如果发现锁被占用,只能阻塞等待,ReentrantLock还提供了一个trylock方法,如果加锁成功,没啥特殊的!如果加锁失败,不会阻塞,直接返回false(让程序员灵活的决定接下来做啥!)
  2. synchronized是一个非公平锁(概率均等,不遵循先来后到)ReentrantLock提供了公平和非公平两种工作模式(在构造方法中,使true——》公平锁)
  3. synchronized搭配wait(),notify()进行等待唤醒,如果多个线程wait()等待同一个对象,notify()的时候是随机唤醒一个!

ReentrantLock则是搭配Condition这个类,这个类也能起到等待通知,可以功能更加强大~

信号量(Semaphore)

停车场外面的一个牌子,显示剩余车位XXX(这就用到信号量)

信号量本质上是一个计数器,描述了当前“可用资源的个数”;

P操作:申请资源,计数器-1,V操作,释放资源,计数器+1

如果计数器已经是0了,继续申请资源,就会阻塞等待~

其实,所谓的“锁”,本质上是计数器为1的信号量

取值只有1和0两种,也叫二元信号量

信号量是更广义的锁,不光能管理非0既1的资源,也能管理多个资源!!

JUC的一些线程安全集合类~

常用的有:ArrayList,LinkList,HashMap,PriorityQueue……线程不安全

如果多线程环境下使用就可能出现问题:

  1. 最直接的方法:使用锁来手动保证!!多个线程去修改Array List此时就可能有问题,就可以给修改操作进行加锁操作!!
  2. 标准库还提供了一些线程安全版本的集合类,如果需要使用ArrayList,则可以使用Vector代替(不建议使用,古老级别)

CopyOnWeriteArrayList支持“写时拷贝”集合类

修改的时候就拷贝一份!!线程安全是多个线程修改不同变量(没加锁)

多线程使用“哈希表”

HaspMap线程不安全肯定不行!!

HashTable线程安全的,也是给关键方法加synchronized(加到方法上,相当于针对this加锁了!)

ConcurrentHashMap推荐方案:

高频面试题:HashTable和ConcurrentHashMap的区别!!(面试高频)

  1. 加锁粒度不同(触发锁冲突的频率)

HashTable是针对整个哈希表加锁,任何的增删改查操作,都会触发加锁,也就都会可能有锁竞争!实际上仔细思考,其实没必要加锁这么勤快!!

HashTable的底层是一个数组+链表

插入元素,根据Key计算hash值——》数组下标,把这个新的元素给挂到对应下标的链表上(Java  Hash Map还会再链表太长的时候,把链表变为红黑树!

如果咱们是两个线程插入元素!

线程1插入的元素对应再下标为1的链表上~

线程2插入的元素对应再下标为2的链表上~

是否存在线程安全问题??两个线程修改不同变量,没啥事,没有线程安全问题!!此时虽然两个操作没有线程安全问题,但是由于synchronized是加到this上的,仍然会针对同一个对象产生锁竞争,产生阻塞等待!!


那么当不只有一把锁的时候:

concurrentHashMap不是只有一把锁了,是每个链表(头节点)作为一把锁!!

每次进行操作,都是针对对应链表的锁进行加锁,操作不同链表就是针对不同的锁进行加锁,不会有竞争!!

该方法导致大部分加锁操作实际上没有锁冲突的,此时,这里的加锁操作的开销就微乎其微了!!

上述内容便是HashTable和ConcurrentHashMap的最大,最核心区别!!

concurrentHashMap是把每个链表的头节点放到synchronized

    void put(String key,String value){//先找到对应链表的头节点int index=hashCode(key);Node head=getHead(index);synchronized (head){//执行链表插入节点的操作}}

上述的情况是从Java8开始的,在Java1.7及其之前,concurrentHashMap使用“分断锁”,目的和上述是类似的,相当于是好几个链表共用一把锁(这个设定是不科学的,效率不够高,代码写起来也很麻烦……)


其他方面的改进:

1.concurrentHashMap更重复的利用了CAS机制——》无锁编程!!

有的操作,比如获取/更新元素个数,就可以直接使用CAS完成,不必加锁了!!CAS也能保证线程安全,往往比锁更高效,但是这个东西咱们也不会经常使用!适用范围不像锁那么广泛!!

2.concurrentHashMap优化了扩容机制

HashTable如果元素过多,就会涉及到扩容——》负载因子0.75!!扩容需要重新申请空间,搬运元素(把元素从旧的哈希表上删除,插入到新的哈希表上),如果元素本身非常多,上亿个,搬运一次,成本就很高,就会导致这一次的put()操作就会非常卡顿!!而concurrentHashMap策略——》化整为零,并不会试图一次性的就把所有元素都搬运过去,而是每次只搬运一小部分 ,当put()触发扩容,此时就会直接创建更大的内存空间!!但是,不会直接把所有元素都搬运过去,而是只搬运一小部分(这样的速度还是比较快的!)此时相当于存在两份hash表了,此时插入元素直接往新表插入,删除元素:元素在哪个表的元素,查找:新表旧表都查看!并且每次操作都搬运一部分过去!

多线程比较复杂,应用非常广泛的东西,程序员必须要扎实掌握!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/82952.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python从入门到精通(一)

自己也有三四年的码龄了&#xff0c;目前&#xff0c;重拾起自己的博客&#xff0c;记录自己的学习笔记&#xff0c;为大家提供优质内容&#xff0c;也来巩固自己的学习内容。 很开心也成功成为了一名研究生&#xff0c;张张的研究方向是图像处理和计算机视觉这一块&#xff0c…

C++QT 作业8

#include "mywind.h" #include "ui_mywind.h" #include <iostream> #include <QIcon> #include <QLabel> #include <QLineEdit> #include <QDebug>//信息调试类 用于输出数据 Mywind::Mywind(QWidget *parent): QWidget(pa…

python3.11版本pip install ddddocr调用时报错got an unexpected keyword argument ‘det‘ 解决

一、如图出现如下问题 ddddocr.__init__() got an unexpected keyword argument det出现问题原因&#xff1a;python3.11默认安装版本就旧版的ddddocr1.0的&#xff0c;所以导致如下报错 二、解决方案一&#xff08;推荐&#xff09; python3.11的环境直接安装这个即可&…

物 理 层

二、物理层 1、物理层的基本概念 物理层的作用:尽可能的屏蔽掉传输媒体和通信手段的差异&#xff0c;使物理层上面的数据链路层感觉不到这些差异&#xff0c;使其只需要考虑如何完成本层的协议和服务 1.1、物理层的主要任务 机械特性&#xff1a;指明接口所用的接线器的形状…

关闭禁用chrome浏览器的阅读清单/强力书签

文章目录 前言操作 前言 阅读清单对我没啥用&#xff0c;还占用我位置&#xff0c;不小心点击到啥的&#xff0c;必须弃用 操作 chrome地址栏输入 chrome://flags/ 搜索book &#xff0c;关掉下面几个功能

Java 华为真题-猴子爬山

需求&#xff1a; 一天一只顽猴想去从山脚爬到山顶&#xff0c;途中经过一个有个N个台阶的阶梯&#xff0c;但是这猴子有一个习惯&#xff1a;每一次只能跳1步或跳3步&#xff0c;试问猴子通过这个阶梯有多少种不同的跳跃方式&#xff1f; 输入描述 输入只有一个整数N&#xff…

MySQL版数据库原理与应用期末复习重点(3)---画E-R图

文章目录 一、题目一1.1 题目描述1.2 解答 二、题目二2.1 题目描述2.2 解答 一、题目一 1.1 题目描述 设开发一个校园公共自行车管理系统&#xff0c;系统需要达到如下要求&#xff1a; &#xff08;1&#xff09;用户能够注册登录&#xff0c;能够根据借车点的名称查询借车…

若依注册的时候给个默认部门出现获取用户信息异常

想在注册的时候在数据库中查询一个部门给它一个默认部门&#xff0c;结果出现异常——【[handleServiceException,59] - 获取用户信息异常】 经分析代码&#xff0c;此方法有如下注解 以上注解会在mapper.xml中做如下操作 在做此操作之前会进入一个拦截器&#xff0c;根据token…

PHP-composer安装扩展安装,批量操作合并pdf

清除Composer缓存&#xff1a; 运行以下命令来清除Composer的缓存&#xff0c;并再次尝试安装包。 bash composer clear-cache 使用不同的镜像源&#xff1a; Composer使用的默认包源可能会受到限制或访问问题。你可以切换到使用其他镜像源&#xff0c;如阿里云、Composer中国…

安理【2022】

关键字&#xff1a; 出栈序列s2固定、快速排序2趟、next数组、二分查找比较次数log2n向上取整、 一、选择 二、填空 三、应用

Zookeeper 启动失败【Cannot open channel to 3 at election address...】

文章目录 完整报错信息解决方法1.检查文件夹权限2.未监听所有IP3.IP映射名称与 ID 不对应 完整报错信息 Cannot open channel to 3 at election address hadoop121/192.168.10.121:3888 java.net.ConnectException 解决方法 1.检查文件夹权限 检查当前用户是否拥有 Zookeep…

《Kubernetes部署篇:Ubuntu20.04基于containerd部署kubernetes1.25.14集群(多主多从)》

一、架构图 如下图所示: 二、环境信息 1、资源下载基于containerd部署容器版kubernetes1.25.14集群资源合集 2、部署规划主机名K8S版本系统版本内核版本IP地址备注k8s-master-121.25.14Ubuntu 20.04.5 LTS5.15.0-69-generic192.168.1.12master节点 + etcd节点k8s-master-131.…

adb shell命令查看当前屏幕可见最顶层Activity和Fragment及其调用栈

adb shell命令查看当前屏幕可见最顶层Activity和Fragment及其调用栈 &#xff08;1&#xff09;当前屏幕可见页面最顶层是哪个Activity: adb shell "dumpsys activity top | grep ACTIVITY | tail -n 1"&#xff08;2&#xff09;当前屏幕可见页面最顶层是哪个Fragm…

(图论) 827. 最大人工岛 ——【Leetcode每日一题】

❓ 827. 最大人工岛 难度&#xff1a;困难 给你一个大小为 n x n 二进制矩阵 grid 。最多 只能将一格 0 变成 1 。 返回执行此操作后&#xff0c;grid 中最大的岛屿面积是多少&#xff1f; 岛屿 由一组上、下、左、右四个方向相连的 1 形成。 示例 1: 输入: grid [[1, 0]…

解决Sublime Text用浏览器打开没反应

点击Open in Browser用浏览器打开没反应怎么解决&#xff1f; 点击Browse Packages 会跳转到这个文件夹页面 打开User文件夹 在文件中添加下面代码即可,chrome是默认打开浏览器&#xff0c;可以自定义为你想用的浏览器 { "browser": "chrome" }

Centos7 安装部署 Kubernetes(k8s) 高可用集群

1&#xff1a;基础环境准备 宿主机系统集群角色服务器IP主机名称容器centos7.6master192.168.2.150ks-m1dockercentos7.6master192.168.2.151ks-n1dockercentos7.6master192.168.2.152ks-n2docker 1.1 服务器初始化及网络配置 VMware安装Centos7并初始化网络使外部可以访问*…

华为HCIA学习(一)

文章目录 一.根据考试题总结知识点&#xff08;一题一点&#xff09;二.上午学习三.下午学习四.今天只做了70题&#xff0c;需要的可以找我 一.根据考试题总结知识点&#xff08;一题一点&#xff09; 二.上午学习 ① VRP系统是VRP是华为公司从低端到高端的全系列路由器、交换…

探讨基于IEC61499 的分布式 ISA Batch 控制系统

ISA SP88 是批次过程控制的标准&#xff0c;对应的IEC标准是IEC 61512。该标准中一个重要的部分是配方管理&#xff08;Recipe Management&#xff09;。 所谓配方&#xff0c;是根据批量产品的要求&#xff0c;材料设定加工工艺&#xff0c;加工流程和参数。类似于传统制造业的…

层次聚类分析

1、python语言 from scipy.cluster import hierarchy # 导入层次聚类算法 import matplotlib.pylab as plt import numpy as np# 生成示例数据 np.random.seed(0) data np.random.random((20,1))# 使用树状图找到最佳聚类数 Z hierarchy.linkage(data,methodweighted,metric…

千呼万唤openGauss资源池化系列培训来了

应openGauss广大用户要求&#xff0c;社区于近期推出openGauss资源池化培训系列。 关于资源池化 资源池化是openGauss 5.0.0 推出的重点特性&#xff0c;是openGauss基于内存池化和共享存储实现的数据库集群。数据在集群的计算节点内存、共享存储中实现共享。应用可以任意节点…