草庐IT

JAVA学习day13

栗悟饭与龟波功004 2023-03-28 原文

首先先简单提一下昨天没有说的线程池

image.png

线程池代码示例,实际开发过程中,一般程序猿用的并不多

锁和死锁

锁是java中用来保证线程操作原子性的一种机制
比较一下,锁是数据库中用来保证事务操作原子性的一种机制
原子性:如果把一个事务看作是一个程序,它要么完整的被执行,要么完全不执行。这种特性就叫原子性。

用到锁的环节

有数据脏读,根据代码应该有10000个线程,但实际并没有达到
image.png
添加synchronized关键字上锁,给代码块上锁。这样就能保证数据每次结果都是10000
image.png
或者直接在方法签名上添加synchronized直接锁方法,锁方法比锁代码块范围更大
image.png

java中的锁有synchronized和Lock锁

synchronized是关键字,可以锁方法和代码块,Lock是类(官方推荐)只能锁代码块

lock锁代码示例

image.png

数据类型分为线程安全类型和线程不安全类型

如果一个数据类型需要我们手动加锁来保证其操作的原子性,那么他就是不安全线程
如果一个数据类型能够自己在方法中加锁来保证其操作的原子性,那么它就是线程安全的
简单列举几个常见的数据类型


image.png

以ArrayList为例

image.png

只有在多线程共享数据的前提下,才需要考虑加锁的问题,一般程序中都不需要用到线程安全

产生死锁的必要条件

互斥条件:

锁要具有排他性(一个资源只能被一个线程占用),在同一时刻锁只能被一个线程持有

请求与保持条件:

一个线程因为请求其他资源被阻塞时,对已获取的资源保持不释放

不剥夺条件:

一个线程没有主动释放资源之前,不能被其他线程强行剥夺的

循环等待条件:

A线程持有资源a的锁,B线程持有资源b的锁,在互相不释放自己资源的前提下,去请求对方持有的锁,这时候会形成双方循环等待,造成永久堵塞

产生死锁的原因

两个线程手上各自持有一个对象的锁,在没有释放的情况下,去请求对方手上的锁,这时候就产生了死锁

如何解决死锁

破坏任意一个条件即可


image.png
1.破坏互斥条件:

用共享锁,在同一时刻,锁可以被多个线程使用

2.破坏请求与保持条件:

一次性申请所有资源

3.破坏不剥夺条件:

一个线程因为请求其他资源被阻塞时,主动释放已获取资源

4.破坏循环等待条件:

所有的线程按照同样的顺序请求资源

集合容器整理

image.png

1.collection 和map的区别

(1)collection和map是官方提供的集合容器的两大体系的顶层接口
(2)collection代表单元素集合体系
(3)map代表kv键值对集合体系
(4)collection体系继承了iterable迭代器接口,所有的子类都提供了迭代器的实现,而map体系没有

2.List,Set,Queue的区别

(1)List,Set,Queue都是collection体系下的子接口,分别代表三个子体系
(2)List体系特点有序不唯一,Set体系特点是无序且唯一,Queue体系特点是先入先出

3.队列和栈的区别

(1)队列是一种FIFO(First in First out)先入先出的结构
(2)栈是一种FILO(First in Last out)先入后出的结构
Java集合体系中的LinkedList可以实现队列和栈结构
在链表头部插入尾部取出或者尾部插入头部取出,就是队列。(插入和取出在不同方向上进行)
在链表头部插入头部取出或者尾部插入尾部取出就是栈(插入和取出在相同方向进行)

4.ArrayList和Array的区别

Array是数组,ArrayList是类
Array是定长的(需要手动扩容),ArrayList长度可变(使用过程中自动扩容)
ArrayList的底层是Array

5.ArrayList和LinkedList的区别

1.底层数据结构实现︰ArrayList底层数据结构是动态数组,而 LinkedList的底层数据结构是双向链表
2.随机访问(即读)效率∶ArrayList比LinkedList在随机访问的时候效率要高,因为ArrayList底层是数组,可以通过索引号快速访问,LinkedList是通过二分查找法遍历链表节点进行查找的
3.增加和删除效率∶在非首尾的增加和删除操作,LinkedList 要比 ArrayList 效率要高,因为ArrayList增删操作需要大量的前移或后移,这个过程中涉及到大量的赋值操作比较耗时间,LinkedList只需要修改节点对象的左右指针即可。
4.内存空间占用:LinkedList 比 ArrayList更占内存,因为 LinkedList的节点除了存储数据,还存储了两个引用,一个指向前一个元素,一个指向后一个元素。
5.综合来说,在需要频繁读取集合中的元素时,更推荐使用ArrayList,而在插入和删除操作较多时,更推荐使用 LinkedList。

6.ArrayList和Vector的区别(可以简单提一下CopyOnWriteArrayList)

ArrayList 是线程不安全的,Vector 是线程安全的,ArrayList中所有的方法都没有加同步锁,Vector中所有方法都加了synchronized同步锁,官方在jdk1.5版本中又推出了一个CopyOnWriteArrayList,使用Lock锁实现线程安全,然后弃用了Vector,因为Lock锁的性能比synchronized锁性能更好。
在并发编程中,如果多个线程共享一个ArrayList,那么必须考虑线程安全问题,可以自己对ArrayList操作的代码加锁或者直接用线程安全的CopyOnWriteArrayList类,在不考虑线程安全的环境下,用ArrayList更好。因为开锁和关锁是很耗性能的

7.Array怎么转换为ArrayList,ArrayList怎么转换为Array

Array就是数组,ArrayList是底层为数组的容器类
(1)官方提供的数组工具类Arrays,提供了一个静态方法asList()可以把数组转换为List,参数是数组,返回值是List
(2)ArrayList类中提供了toArray方法,可以吧ArrayList转换为Array后进行返回

8.HashSet和TreeSet

HashSet和TreeSet都是Set接口下的子类
HashSet的底层是HashMap,他将数据存储在HashMap的key中
HashSet是无序的唯一的,因为HashMap的key是无序唯一的
TreeSet的底层是TreeMap,他将数据存储在TreeMap的key中
HashSet是有序的,唯一的,因为TreeMap的key是有序唯一的

9.Map接口体系

HashMap和HashTable区别(带一下ConcurrentHashMap)

HashMap是线程不安全的,HashTable是线程安全的,HashMap中所有的方法都没有加同步锁,HashTable中所有方法都加了synchronize同步锁,官方在jdk1.5版本中又推出了一个ConcurrentHashMap,使用Lock锁实现线程安全,然后弃用了HashTable,因为Lock锁的性能比synchronized锁性能更好。
在并发编程中,如果多个线程共享一个HashMap,那么必须考虑线程安全问题,可以自己对HashMap操作的代码加锁或者直接用线程安全的ConcurrentHashMap类,在不考虑线程安全的环境下,用HashMap更好。因为开锁和关锁是很耗性能的

对Null key支持:HashMap支持key为null,但只能为一,HashTable不支持k为空,会直接抛出NPE,HashMap和HashTable支持value为空,不限制个数,ConcurrentHashMap的key和value都不支持为空

HashMap在1.8以后,设置了阈值=8,当链表长度超过阈值的时候,会把链表转换成红黑树,以此减少检索时间,HashTable被弃用了,没有更新

10.初始容量大小和扩容容量大小的区别

HashMap默认初始容量是16,扩容策略是原来长度的2倍
HashTable默认初始容量是11,扩容策略是原来是2n+1
HashMap如果手动指定了初始容量,不是2的n次方,他也会找到最紧接的一个2的n次方作为初始容量;HashTable如果手动指定了初始容量,会直接诶使用给定的大小;
Hashtable如果手动指定了初始容量,会直接使用给定的消失
Hashtable采用的锁全表机制,ConcurrentHashMap采用了分段锁的设计,锁粒度更细,性能更好

11.Hashmap和Treemap的区别

HashMap的底层是数组+链表/红黑树,key是无序的,唯一的
TreeMap的底层是红黑树,key是有序的唯一的
Hashmap的性能比TreeMap更好

12.HashMap的底层原理(数据结构+put()流程 + resize()扩容策略)

HashMap的底层是数组+链表/红黑树
1.根据数组中节点为null,创建新的节点对象,把k, v存储在节点对象中,把节点对象存储在数组中。2.如果数组的节点不为null,判断节点的key与插入元素的key是否相等。
1.相等,直接用新的k,v覆盖原节点中的k,V。
2.不相等,判断此时节点是否为红黑树。
1.是红黑树,创建红黑树节点对象存储k,V,插入到红黑树中。
2.不是红黑树,创建链表节点对象存储k,v,插入到链表中,判断链表长度是否大于阈值8。
3.判断++size是否大于阈值,是就扩容。

HashMap默认初始容量是16
resize()方法是在hashmap中的size大于阈值时或者初始化时,就调用resize方法进行扩容每次扩容的时候始终是原数组长度的2倍,即长度永远是2的n次方
扩容后节点对象的位置要么在原位置,要么偏移到两倍的位置

13.HashMap的长度为什么是2的幂次方

HashMap长度为2的幂次方的原因是为了减少Hash碰撞,尽量使Hash算法的结果均匀。

14.什么是哈希碰撞/哈希冲突,怎么解决哈希冲突,HashMap采用的策略

如果有两个字符串通过同样的哈希算法计算出来的哈希码一样,则称他们发生了哈
希碰撞/哈希冲突。
解决Hash冲突方法有:开放定址法、链地址法(拉链法)。HashMap中采用的是链地址法。
链地址法(拉链法),将哈希值相同的元素构成一个同义词的单链表,并将单链表的头指针存放在哈希表的第i个单元中,查找、插入和删除主要在同义词链表中进行。链表法适用于经常进行插入和删除的情况。

15. HashMap为什么不直接使用key的hashCode()函数返回的哈希码作为落槽时的索引号, HashMap是怎么解决的呢

这题也可以这样问"HashMap的底层是如何计算key落槽时的索引的”
hashCode()方法返回的是 int整数类型,其范围为-(231)~(231-1),约有40亿个映射空间,而 HashMap的容量范围是在16(初始化默认值)~2N 30,HashMap通常情况下是取不到最大值的,并且设备上也难以提供这么多的存储空间,从而导致通过hashCode()计算出的哈希值可能不在数组大小范围内,进而无法匹配存储位置;
HashMap自己实现了自己的 hash()方法,通过两次扰动使得它自己的哈希值高低位自行进行异或运算,降低哈希碰撞概率也使得数据分布更平均。

16.==和equals()方法的区别

==和equals()都可以用来进行比较,语法是a ==b或者a.equals(b)
==比较的是内存地址,equals()方法是Object中的方法,可以被任意类继承或者重写,通过看官方Object类原码可以知道equals()方法默认也是用==比较内存地址
如果想要修改equals()方法的比较规则,可以重写equals()方法,String类就重写equals()方法的比较规则,由默认的比较两个字符串对象的内存地址,修改为比较字符串中每个字符是否相等
因为堆区中可能会出现两个一模一样的字符串,但用==比较会返回false,因为其内容一样但内存地址不一样,所以字符串比较必须用equals方法,否则就会出现两个一模一样的字符串,因为地址不一样,比较后出现不相等的情况

17.为什么重写了hashCdoe()方法,必须重写equals()方法(反过来问也一样)

如果两个对象equals相等,其hashcode必然相等,如果equals相等,hashcode不相等就不能保证唯一性
HashMap底层采用了key的hashcode()来计算数组的索引index
如果数组[index]为空说明key不存在,直接落槽插入
如果数组[index]不为空,说明该位置有key存在,但不能一定说明一存在的key与要插入的key重复,因为可能会发生哈希碰撞,此时应该进一步用equals方法比较已存在的key与要插入的key是否相等。如果相等就说明一定是重复的,应该覆盖,如果不相等,说明发生了哈希碰撞,应该插入链表中
重写equals方法的目的是为了不去比较两个对象的内存地址,改为比较对象的内容,如果一个类重写了equals没有hashcode就可能出现两个地址不同的对象,equals比较相等但是hashcode比较不相等,这样会违反hashmap的唯一性,因此重写了equals方法,必须也要重写hashcode方法,且必须满足两个对象equals相等,hashcode也必须相等

有关JAVA学习day13的更多相关文章

  1. java - 等价于 Java 中的 Ruby Hash - 2

    我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/

  2. java - 从 JRuby 调用 Java 类的问题 - 2

    我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www

  3. java - 我的模型类或其他类中应该有逻辑吗 - 2

    我只想对我一直在思考的这个问题有其他意见,例如我有classuser_controller和classuserclassUserattr_accessor:name,:usernameendclassUserController//dosomethingaboutanythingaboutusersend问题是我的User类中是否应该有逻辑user=User.newuser.do_something(user1)oritshouldbeuser_controller=UserController.newuser_controller.do_something(user1,user2)我

  4. java - 什么相当于 ruby​​ 的 rack 或 python 的 Java wsgi? - 2

    什么是ruby​​的rack或python的Java的wsgi?还有一个路由库。 最佳答案 来自Python标准PEP333:Bycontrast,althoughJavahasjustasmanywebapplicationframeworksavailable,Java's"servlet"APImakesitpossibleforapplicationswrittenwithanyJavawebapplicationframeworktoruninanywebserverthatsupportstheservletAPI.ht

  5. Observability:从零开始创建 Java 微服务并监控它 (二) - 2

    这篇文章是继上一篇文章“Observability:从零开始创建Java微服务并监控它(一)”的续篇。在上一篇文章中,我们讲述了如何创建一个Javaweb应用,并使用Filebeat来收集应用所生成的日志。在今天的文章中,我来详述如何收集应用的指标,使用APM来监控应用并监督web服务的在线情况。源码可以在地址 https://github.com/liu-xiao-guo/java_observability 进行下载。摄入指标指标被视为可以随时更改的时间点值。当前请求的数量可以改变任何毫秒。你可能有1000个请求的峰值,然后一切都回到一个请求。这也意味着这些指标可能不准确,你还想提取最小/

  6. 【Java 面试合集】HashMap中为什么引入红黑树,而不是AVL树呢 - 2

    HashMap中为什么引入红黑树,而不是AVL树呢1.概述开始学习这个知识点之前我们需要知道,在JDK1.8以及之前,针对HashMap有什么不同。JDK1.7的时候,HashMap的底层实现是数组+链表JDK1.8的时候,HashMap的底层实现是数组+链表+红黑树我们要思考一个问题,为什么要从链表转为红黑树呢。首先先让我们了解下链表有什么不好???2.链表上述的截图其实就是链表的结构,我们来看下链表的增删改查的时间复杂度增:因为链表不是线性结构,所以每次添加的时候,只需要移动一个节点,所以可以理解为复杂度是N(1)删:算法时间复杂度跟增保持一致查:既然是非线性结构,所以查询某一个节点的时候

  7. ruby - 安装libv8(3.11.8.13)出错,Bundler无法继续 - 2

    运行bundleinstall后出现此错误:Gem::Package::FormatError:nometadatafoundin/Users/jeanosorio/.rvm/gems/ruby-1.9.3-p286/cache/libv8-3.11.8.13-x86_64-darwin-12.gemAnerroroccurredwhileinstallinglibv8(3.11.8.13),andBundlercannotcontinue.Makesurethat`geminstalllibv8-v'3.11.8.13'`succeedsbeforebundling.我试试gemin

  8. LC滤波器设计学习笔记(一)滤波电路入门 - 2

    目录前言滤波电路科普主要分类实际情况单位的概念常用评价参数函数型滤波器简单分析滤波电路构成低通滤波器RC低通滤波器RL低通滤波器高通滤波器RC高通滤波器RL高通滤波器部分摘自《LC滤波器设计与制作》,侵权删。前言最近需要学习放大电路和滤波电路,但是由于只在之前做音乐频谱分析仪的时候简单了解过一点点运放,所以也是相当从零开始学习了。滤波电路科普主要分类滤波器:主要是从不同频率的成分中提取出特定频率的信号。有源滤波器:由RC元件与运算放大器组成的滤波器。可滤除某一次或多次谐波,最普通易于采用的无源滤波器结构是将电感与电容串联,可对主要次谐波(3、5、7)构成低阻抗旁路。无源滤波器:无源滤波器,又称

  9. CAN协议的学习与理解 - 2

    最近在学习CAN,记录一下,也供大家参考交流。推荐几个我觉得很好的CAN学习,本文也是在看了他们的好文之后做的笔记首先是瑞萨的CAN入门,真的通透;秀!靠这篇我竟然2天理解了CAN协议!实战STM32F4CAN!原文链接:https://blog.csdn.net/XiaoXiaoPengBo/article/details/116206252CAN详解(小白教程)原文链接:https://blog.csdn.net/xwwwj/article/details/105372234一篇易懂的CAN通讯协议指南1一篇易懂的CAN通讯协议指南1-知乎(zhihu.com)视频推荐CAN总线个人知识总

  10. 深度学习部署:Windows安装pycocotools报错解决方法 - 2

    深度学习部署:Windows安装pycocotools报错解决方法1.pycocotools库的简介2.pycocotools安装的坑3.解决办法更多Ai资讯:公主号AiCharm本系列是作者在跑一些深度学习实例时,遇到的各种各样的问题及解决办法,希望能够帮助到大家。ERROR:Commanderroredoutwithexitstatus1:'D:\Anaconda3\python.exe'-u-c'importsys,setuptools,tokenize;sys.argv[0]='"'"'C:\\Users\\46653\\AppData\\Local\\Temp\\pip-instal

随机推荐