多线程使用HashMap,HashMap和HashTable和ConcurrentHashMap区别(面试题常考),硬盘IO,顺便回顾volatile(一)

简介: 多线程使用HashMap,HashMap和HashTable和ConcurrentHashMap区别(面试题常考),硬盘IO,顺便回顾volatile

一、回顾💛

谈谈volatile关键字用法

volatile能够保证内存可见性,会强制从主内存中读取数据,此时如果其他线程修改被volatile修饰的变量,可以第一时间读取到最新的值。

二、💙

HashMap线程不安全没有锁,HashTable线程更加安全,关键方法都提供了synchronized,CocurrrentHashMap是线程安全的hash表

HashMap是在方法中直接加上synchronized,就相当于针对this(当前对象)加锁,

HashTable——全局锁,会安全,但是缺点就是有巨大的锁开销,会形成阻塞等待

HashTable<String,String>ht=......;

hs.set("aaa","111")

任意的针对ht对象的操作,都会涉及针对this的加锁,此时如果多个线程想操作ht,就一定会触发激烈的锁竞争,最后都只能一个一个排着队,依次执行——并发

所以会出现CocurrentHashMap

我们学过的哈希表的二次探测,真实hash表基本不会出现,而是采用链表的方式(哈希桶),如果修改操作是像下图这样,针对两个不同的链表进行修改,是否存在线程安全问题->当然不会

但是假如说是扩容,就可能会有影响了,但是扩容是很有重量级的操作,把整个的哈希表都需要重新搬运一遍,这样锁的开销也就微乎其微。

那么有人也会问-假如上面那种是不是说明这种我就完全不需要加锁了,反正也是没有线程安全问题,但是也不行,因为下图这种,假如说去插入两个在同一个链表的位置,又会涉及到线程的安全问题——解决方法每个链表都安排一把锁-这样开销就会小很多,这样第二个操作就会陷入阻塞等待,因为第一个正在修改,这样这个问题就解除了。

一个hash表上链表个数这么多,两个线程正好在同时修改一个链表的操作本身就概率比较低,整体锁的开销大大降低了,这么修改也就不会有这么多的线程阻塞。

此时可能此时有人问,该怎么给每个线程加锁呢——由于synchronized随意对象都可以加锁,所以可以简单使用每个链表的头节点使用。

这也就是我们的改进

1.ConcurrentHashMap减小了锁的粒度,每个链表有一把锁,大部分情况下都没有涉及锁冲突。

2.广泛使用了CAS操作,size++,这样的操作也不会存在锁冲突

3.写操作进行了加锁(链表级)读操作,不加锁了就——如果有一个线程读,一个线程写会有问题吗,最多就是修改的一瞬间,读到一个旧版本/新版本的数据,不确定而已,通过一些精密的操作,保证不会读“半个数据”(有新有旧)

4.针对扩容操作进行优化,渐进式扩容

HashTable一旦触发扩容,就会一口气完成所有元素的搬运,这个过程非常耗时间,我们的大部分请求会很顺畅,但是突然一个请求会卡很久——而且并不好确认哪里的问题,因为这个触发概率很小,很气。

所以这个改进——化整为零,当需要扩容时,创建一个更大的数据,然后把旧的数据逐渐往新的数据哈桑搬运,会出现一段时间——新,旧数组共同存在的时间——

1.新增数据,就往新数组上插入

2.删除数据,把旧的数组上的数据删除掉即可

3.查找元素,新旧数据都要查

4.修改元素,统一把这个元素放到新的数组上

与此同时,每个操作都会触发一定到搬运,每搬运一次,就可以保证整体时间不是很大,积少成多之后,逐渐完成搬运了,也就可以把之前的旧的数组销毁了

上面说的是HashTable和ConcurrentHashMap的区别

HashMap和ConcurrentHashMap的区别,就是线程安全和不安全的区别。

treeMap和hashMap区别——哈希表和红黑树之间的区别

面试有可能问一手

ConcurrentHashMap的分段锁

Java8之前,ConcurrentHashMap的分段锁区别

Java8之后就没有分段锁了

ConcurrentHashMap的分段锁确实可以提高效率,但是不如一个链表一把锁效率更高,而且分段锁的维护更加麻烦。

三、 💜

文件IO操作

文件->存储数据的方式

操作系统通过“文件系统”这样的模块来管理硬盘。

文件~不同的文件系统,管理文件的方式都是一致的

通过“目录”构成了N叉树的文件结构

如D盘->tmp->cat.jpg通过这个路线就可以找到确定电脑的唯一一个文件,这个路线就叫做路径。

以盘符开头的路径,也叫做绝对路径,绝对路径是从电脑这里出发找文件的过程。

以···或···开头的路径,叫做绝对路径,相对路径,需要有一个基准目录/工作目录,表示从这个基准目录出发怎么才能找到这个文件

如以D:为基准目录

.白哦是当前所在目录

./tmp/cat.jpg

以D:/tmp为基准

./cat.jpg

..表示当前目录的上一层目录

如果D:/tmp/111为基准(是以tmp开始查找)

../cat.jpg    

D:/tmp/111/aaa为基准

../../cat.jpg(也是以tmp开始查找)

文件系统存储的文件具体分为两个大类:

1.文本文件

utf8就是一个大表(实际上)表上数据的集合叫做字符。

2.二进制文件

二进制数据

如何区分呢?

一个最简单的方式判断就是:文件是二进制还是文本,直接使用记事本打开,如果打开之后能看懂,就是文本文件,假如看不懂,就是二进制文件,记事本打开文件,就会尝试把当前数据在码表中查询~

word文档就是二进制文件(功能太多了,属于是“富文本”需要用二进制去组织),后续文本的操作,文本和二进制操作方式完全相同的

文件系统的操作——

1.创建文件

2.删除文件

3.创建目录

通过一个类的使用——java.io.File(IO-Input和output,站在cpu的角度,来看待输入输出。)

通过File对象描述一个具体的文件,File对象可对应一个真实的文件,也可对应一个不存在的文件。

File(String pathname)此处参数字符串表示一个路径,可以是绝对路径,也可以是相对路径

站在操作系统的角度来看,目录也是文件,操作系统中的文件是更为广义的概念,具体里面有很多种不同的类型

1.普通文件(通常见到的文件)

2.目录文件(通常见到的文件夹)<-(高级,文件夹太土鳖的)

1.File file=new File("./test.txt");             //路径随意填写(可以不存在)

2.file.createNewFile()//创建文件(有可能抛异常)

3.file.delete(删除掉文件)

file.deleteOnExit(),(这个是程序退出后再删除,不是立刻删除)有的时候,可能会有这样一个功能,临时文件程序运行的时候,搞一个临时文件,程序结束了,临时文件会自动进行删除。

像是office等生产力软件,都有生产临时文件功能,这个临时文件就自动存储了你当前的编辑状态,如果有人word长期不保存,突然断电关机,此时你在进行重启,由于刚才是非正常关闭,临时文件来不及删除是仍然存在的,office启动就能知道上次是异常关闭,就会提醒你是否要从之前的临时文件恢复未保存的结果。

创建一个目录,

import java.io.File;
import java.io.IOException;
public class Demo11 {
    public static void main(String[] args) throws IOException {
        File file=new File("./d.txt");
        //创建文件
   // file.createNewFile();
        //删除掉文件
  //  file.deleteOnExit();
        //创建一层目录mk->make,dir->directory
        //mkdir()一次只能创建一级目录
       file.mkdir();
  //  mddirs能创建多极目录
         file.mkdirs();
    }
}

 


相关文章
|
6月前
|
存储 安全 Java
Java 集合框架中的老炮与新秀:HashTable 和 HashMap 谁更胜一筹?
嗨,大家好,我是技术伙伴小米。今天通过讲故事的方式,详细介绍 Java 中 HashMap 和 HashTable 的区别。从版本、线程安全、null 值支持、性能及迭代器行为等方面对比,帮助你轻松应对面试中的经典问题。HashMap 更高效灵活,适合单线程或需手动处理线程安全的场景;HashTable 较古老,线程安全但性能不佳。现代项目推荐使用 ConcurrentHashMap。关注我的公众号“软件求生”,获取更多技术干货!
111 3
|
7月前
|
安全
HashTable与HashMap的区别
(1)HashTable的每个方法都用synchronized修饰,因此是线程安全的,但同时读写效率很低 (2)HashTable的Key不允许为null (3)HashTable只对key进行一次hash,HashMap进行了两次Hash (4)HashTable底层使用的数组加链表HashTable与HashMap的区别
121 2
|
7月前
|
安全
ConcurrentHashMap原如何保证的线程安全?
JDK1.7:使用分段锁,将一个Map分为了16个段,每个段都是一个小的hashmap,每次操作只对其中一个段加锁 JDK1.8:采用CAS+Synchronized保证线程安全,每次插入数据时判断在当前数组下标是否是第一次插入,是就通过CAS方式插入,然后判断f.hash是否=-1,是的话就说明其他线程正在进行扩容,当前线程也会参与扩容;删除方法用了synchronized修饰,保证并发下移除元素安全
194 2
|
8月前
|
存储 开发者
HashMap和Hashtable的key和value可以为null吗,ConcurrentHashMap呢
HashMap的key可以为null,value也可以为null;Hashtable的key不允许为null,value也不能为null;ConcurrentHashMap的key不允许为null
|
7月前
|
存储 缓存 Java
大厂面试高频:Volatile 的实现原理 ( 图文详解 )
本文详解Volatile的实现原理(大厂面试高频,建议收藏),涵盖Java内存模型、可见性和有序性,以及Volatile的工作机制和源码案例。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
大厂面试高频:Volatile 的实现原理 ( 图文详解 )
|
8月前
|
自然语言处理 Java 数据处理
Java IO流全解析:字节流和字符流的区别与联系!
Java IO流全解析:字节流和字符流的区别与联系!
306 1
|
9月前
|
Java 大数据 API
Java 流(Stream)、文件(File)和IO的区别
Java中的流(Stream)、文件(File)和输入/输出(I/O)是处理数据的关键概念。`File`类用于基本文件操作,如创建、删除和检查文件;流则提供了数据读写的抽象机制,适用于文件、内存和网络等多种数据源;I/O涵盖更广泛的输入输出操作,包括文件I/O、网络通信等,并支持异常处理和缓冲等功能。实际开发中,这三者常结合使用,以实现高效的数据处理。例如,`File`用于管理文件路径,`Stream`用于读写数据,I/O则处理复杂的输入输出需求。
448 12
|
10月前
|
存储 Java 开发者
HashMap线程安全问题大揭秘:ConcurrentHashMap、自定义同步,一文让你彻底解锁!
【8月更文挑战第24天】HashMap是Java集合框架中不可或缺的一部分,以其高效的键值对存储和快速访问能力广受开发者欢迎。本文深入探讨了HashMap在JDK 1.8后的底层结构——数组+链表+红黑树混合模式,这种设计既利用了数组的快速定位优势,又通过链表和红黑树有效解决了哈希冲突问题。数组作为基石,每个元素包含一个Node节点,通过next指针形成链表;当链表长度过长时,采用红黑树进行优化,显著提升性能。此外,还介绍了HashMap的扩容机制,确保即使在数据量增大时也能保持高效运作。通过示例代码展示如何使用HashMap进行基本操作,帮助理解其实现原理及应用场景。
145 1
|
10月前
|
开发者 C# UED
WPF与多媒体:解锁音频视频播放新姿势——从界面设计到代码实践,全方位教你如何在WPF应用中集成流畅的多媒体功能
【8月更文挑战第31天】本文以随笔形式介绍了如何在WPF应用中集成音频和视频播放功能。通过使用MediaElement控件,开发者能轻松创建多媒体应用程序。文章详细展示了从创建WPF项目到设计UI及实现媒体控制逻辑的过程,并提供了完整的示例代码。此外,还介绍了如何添加进度条等额外功能以增强用户体验。希望本文能为WPF开发者提供实用的技术指导与灵感。
381 0
|
10月前
|
存储 安全 Java
Hashtable 和 HashMap 的区别
【8月更文挑战第22天】
274 0

热门文章

最新文章