后端整理(集合框架、IO流、多线程)
1. 集合框架
Java集合类主要有两个根接口Collection和Map派生出来
Collection派生两个子接口
- List
List代表了有序可重复集合,可以直接根据元素的索引进行访问 - Set
Set代表无序不可重复集合,只能根据元素本身进行访问
Map接口派生
Map代表的是存储key-value对的集合,可根据元素的key来访问value
1.1 List
List集合特点:有索引,可重复,有序
扩容机制
- 初始值为10
- 如果数组的长度小于需要的最小容量则自动扩容
- 扩容到原来的1.5倍
ArrayList
底层通过数组实现,查询快,增删慢,线程不安全
访问数据的时间复杂度是O(1)
LinkedList
底层通过双向 链表实现,查询慢,增删快,线程不安全
访问数据的时间复杂度是O(n)
Vector
List接口的古老实现类。线程安全,执行效率低
扩容机制不同于ArrayList,由1.5倍改成1倍
1.2 Set
1.2.1 HashSet
其底层HashMap,也就是数组+链表+红黑树(JDK8)的结构
HashSet集合特点:无序,不可重复,无索引
扩容机制
HashSet底层也是数组,初始容量为16,当使用了超过0.75,即16*0.75=12时,就会扩大容量为原来的两倍
什么情况下为转为红黑树
当链表长度 >= 8,数组长度 >= 64时,会转为红黑树
LinkedHashSet
继承于HashSet,底层是LinkedHashMap,是一个有序去重集合,线程不安全
有序因为它根据hashCode决定元素的存储位置,同时使用链表来维护元素的次序
1.2.2 TreeSet
TreeSet是SortedSet接口的实现类,底层是红黑树,元素有序
排序方式
自然排序(实现Comparable接口)和 定制排序(Comparator)
1.3 Map
Map集合特点
- 键值对(key-value)映射关系
- 是单向的一对一关系,即一个键对应一个值
- 键不可重复,值可重复
- 无序
1.3.1 HashMap
HashMap的底层在jdk7及以前,是数组+链表;jdk8及以后,是数组+链表+红黑树
如何判断重复
先比较hashcode,若相同则使用equals比较插入的值,若值不同,则插入,若值不同,则不插入
2 IO流
IO流的体系
IO流的四大类
- 字节输入流: 以内存为基准,把磁盘文件/网络中的数据以字节的形式读入到内存中去
- 字节输出流: 以内存为基准,把内存中的数据以字节的形式写出到磁盘文件或网络中去
- 字符输入流: 以内存为基准,来自磁盘文件/网络中的数据以字符的形式读入内存中
- 字符输出流: 以内存为基准,把内存中的数据以字符的形式写出到磁盘文件或网络中去
2.1 IO流实现文件的上传下载
2.1.1 文件上传
文章引用IO流–文件上传实现(侵删)
文件上传,我们就需要的一个服务器和客户端,两者需要进行通信,两者通信的要素是服务器的IP地址和对应的端口号才能建立连接
- 首先开启服务器,并开启一个端口号给客户端进行连接通信
serverSocket = new ServerSocket(port);
- 服务器通过监听端口来进行确定是否有客户端进行访问
socket = serverSocket.accept();
- 服务器准备完成,可以与客户端进行通信,首先客户端创立连接
socket = new Socket(InetAddress.getByName(IP), port);
- 连接成功,然后通过IO流进行文件传输,先读取文件,再将文件转为IO流输出(读取是本地读取,输出是输出给服务端)
//2.然后向服务器发送消息,需要一个输出流os = socket.getOutputStream();//3.读取本地的文件并输出,需要一个输入流is = new FileInputStream("123.txt");
- 客户端需要通过一个缓冲区来让文件实现完整的上传和输出,通过一个字节数组,保证整个文件不会因为字符数量的大小导致文件上传失败
//4.读取文件中的内容并输出,读取文件的内容需要一个字节流,用字节数组来接收byte[] buffer = new byte[1024];//这个字节数组是属于IO流中的缓冲区,int length ;while ((length=is.read(buffer) )!= -1){os.write(buffer,0,length);}
- 到这一步,客户端的任务完成了大半,然后就是服务器端的接受操作,与客户端也是大同小异,通过文件字节输入流和文件字节输出流对连接中的数据进行读取和输出
//1.先创建一个端口号供客户端去连接,其实应该先有一个服务器端口号,那客户端才能连上(怎么创建一个端口号?)serverSocket = new ServerSocket(8099);//2.服务器监听端口号,看端口号是否有客户端连接socket = serverSocket.accept();//3.创建一个输入流和一个输出流,输入流用于接收客户端传来的数据,输出流用于输出is = socket.getInputStream();//在建立起的连接中获取信息os = new FileOutputStream("receive.txt");//这里输出的用的是文件流int len ;byte[] bytes = new byte[1024];while ((len = is.read(bytes)) != -1){os.write(bytes,0,len);}
完整代码实现
客户端
/**客户端*/
public class TcpClient {public static void main(String[] args) {Socket socket = null;OutputStream os = null;FileInputStream is = null;try {//1.客户端要连接服务器,需要创建一个连接,创建连接需要服务器的IP号和对应的端口号socket = new Socket(InetAddress.getByName("127.0.0.1"), 8099);//2.然后向服务器发送消息,需要一个输出流os = socket.getOutputStream();//3.读取本地的文件并输出,需要一个输入流is = new FileInputStream("123.txt");//4.读取文件中的内容并输出,读取文件的内容需要一个字节流,用字节数组来接收byte[] buffer = new byte[1024];//这个字节数组是属于IO流中的缓冲区,int length ;while ((length=is.read(buffer) )!= -1){os.write(buffer,0,length);}} catch (IOException e) {e.printStackTrace();}finally {//5.关闭连接if (is != null){try {is.close();} catch (IOException e) {e.printStackTrace();}}if (os != null){try {os.close();} catch (IOException e) {e.printStackTrace();}}if (socket != null){try {socket.close();} catch (IOException e) {e.printStackTrace();}}}}
}
服务器
/**服务器*/
public class TcpServer {public static void main(String[] args) {ServerSocket serverSocket = null;Socket socket = null;InputStream is = null;FileOutputStream os =null;try {//1.先创建一个端口号供客户端去连接,其实应该先有一个服务器端口号,那客户端才能连上(怎么创建一个端口号?)serverSocket = new ServerSocket(8099);//2.服务器监听端口号,看端口号是否有客户端连接socket = serverSocket.accept();//3.创建一个输入流和一个输出流,输入流用于接收客户端传来的数据,输出流用于输出is = socket.getInputStream();//在建立起的连接中获取信息os = new FileOutputStream("receive.txt");//这里输出的用的是文件流int len ;byte[] bytes = new byte[1024];while ((len = is.read(bytes)) != -1){os.write(bytes,0,len);}} catch (IOException e) {e.printStackTrace();}finally {if (os != null){try {os.close();} catch (IOException e) {e.printStackTrace();}}if (is != null){try {is.close();} catch (IOException e) {e.printStackTrace();}}if (socket != null){try {socket.close();} catch (IOException e) {e.printStackTrace();}}if (serverSocket != null){try {serverSocket.close();} catch (IOException e) {e.printStackTrace();}}}}
}
2.1.2 文件下载
文章引用利用io流下载文件(侵删)
public void download(HttpServletRequest request, HttpServletResponse response) {InputStream fis=null;OutputStream toClient=null;try {//获取下载的路径File file=new File("C:\\Users\\kinggao1\\Desktop\\工作周总结.docx");//获取文件名String filename=file.getName();//取得文件的后缀名String ext=filename.substring(filename.lastIndexOf(".")+1).toUpperCase();//以流的形式下载文件fis=new BufferedInputStream(new FileInputStream(file));System.out.println("文件大小:"+fis.available());//创建一个和文件一样大小的缓存区byte[] buffer=new byte[fis.available()];//读取流fis.read(buffer);//清空首部空白行response.reset();//设置文件下载后的指定文件名response.addHeader("Content-Disposition", "attachment;filename=" + new String(filename.getBytes("gb2312"),"ISO8859-1"));response.addHeader("Content-Length", "" + file.length());//response.getOutputStream() 获得字节流,通过该字节流的write(byte[] bytes)可以向response缓冲区中写入字节,再由Tomcat服务器将字节内容组成Http响应返回给浏览器。toClient = new BufferedOutputStream(response.getOutputStream());response.setContentType("application/octet-stream");//将buffer 个字节从指定的 byte 数组写入此输出流。toClient.write(buffer);//刷新此缓冲的输出流。这迫使所有缓冲的输出字节被写出到底层输出流中。 把缓存区的数据全部写出toClient.flush();} catch (IOException e) {e.printStackTrace();} finally {try {//关闭流fis.close();//关闭缓冲输出流toClient.close();} catch (IOException e) {e.printStackTrace();}}}
2.2 IO流实现文件上传时限制文件大小
获取文件IO流的大小
long fileLenght = getFileLenght(file);
再和给定大小判断
如果超出就跑出自定义异常
3 线程
3.1 4种线程的创建方法
- 继承Thread方法,实现run方法
- 实现Callable接口,重写call方法
- 实现Runnable接口,重写run方法
- 线程池构建线程
3.2 线程的状态
3.3 自定义线程池的核心参数
- 核心线程数
- 最大线程数
- 最大存活时间
- 最大存活时间单位
- 阻塞队列
- 线程工厂
- 拒绝策略
拒绝策略有四种:
- 抛出异常
- 把处理返回给调用者,谁调用谁处理
- 直接拒绝
- 清理掉最早的线程,再加入新建的线程
3.4 锁
文章参考于阿里面试失败后,一气之下我图解了Java中18把锁
3.4.1 悲观锁
悲观锁相当与生活中悲观的人,什么事都会忘坏的方向思考
具体来说,就是一个共享数据加了悲观锁,那么线程每次想要操作数据时,都会考虑数据可能也会被其他线程操作,所以每次操作前都会上锁,这样别的线程想要操作这个数据但是没有锁只能够阻塞了
Java中,synchronized就是一种典型的悲观锁
3.4.2 乐观锁
与悲观锁相反,乐观锁相当于生活中的一个乐观的人,什么事情都会往好的方向进行思考
所以,乐观锁在操作数据时不会给共享数据上锁,但是会在更新的时候判断在此期间是否会有其他线程对数据进行了更新
乐观锁可以使用<font color="pink"版本号机制和CAS算法实现,在Java语言中 java.util.concurrent.atomic 包下的原子类就是使用CAS乐观锁实现的
两种锁的使用场景
乐观锁适用于冲突小(可以理解为读多写少)的场景,因为不用上锁,释放锁,省去了锁的开销,从而提升了吞吐量
悲观锁适用于写多读少的场景,冲突比较严重,线程竞争比较激烈,使用乐观锁就是导致线程不断的进行重试,这样还可能降低了性能
3.4.3 互斥锁
互斥锁是独占锁的一种常规实现,是指某一资源同时只允许一个访问者对其进行访问,具有唯一性和排他性
互斥锁一次只能一个线程拥有互斥锁,其他线程只有等待。
3.4.4 自旋锁
自旋锁是指线程在没有获得锁资源时不是直接挂起,而是执行一个忙循环,这个忙循环就是所谓的自旋
相关文章:

后端整理(集合框架、IO流、多线程)
1. 集合框架 Java集合类主要有两个根接口Collection和Map派生出来 Collection派生两个子接口 List List代表了有序可重复集合,可以直接根据元素的索引进行访问Set Set代表无序不可重复集合,只能根据元素本身进行访问 Map接口派生 Map代表的是存储key…...

C++ 类和对象篇(二) this指针
目录 一、this指针概念 二、this指针的特性 三、this指针存在哪里? 四、this指针可以为空吗? 一、this指针概念 1.是什么? 它是类内非静态成员函数的隐含形参,this指针指向调用该函数的对象。 this指针是C编译器给每个“非静态…...

Excel快捷键F1-F9详解:掌握实用快捷操作,提升工作效率
Excel是广泛应用于办公场景的优质电子表格软件,然而,许多人只是使用鼠标点击菜单和工具栏来完成操作,而忽略了快捷键的威力。在本文中,我们将详解Excel中的F1-F9快捷键,帮助您掌握实用的快捷操作,提升工作效…...
Webpack 安装教程
Webpack 是一个前端资源加载/打包工具。 安装 Webpack 使用 cnpm 安装 webpack: cnpm install webpack -g 创建项目 接下来我们创建一个目录 app: mkdir app 在 app 目录下添加 runoob1.js 文件,代码如下: app/runoob1.js 文件…...

移远通信首批加入“5G+eSIM计算终端产业合作计划”,助力大屏移动终端全时在线
7月29日,在全球数字娱乐产业盛会 ChinaJoy上,中国联通携手高通公司、GSMA发布了“5GeSIM 计算终端产业合作计划”。 作为全球领先的物联网整体解决方案供应商,移远通信首批加入该计划,副总经理刘明辉受邀参加5GeSIM 计算终端产业合…...
全网最强大的工具箱—utools介绍及分享
今天来介绍一个相见恨晚的PC端工具——utools,什么是utools?用其自身的话来说:“uTools是一个极简、插件化、跨平台的现代化桌面软件。通过自由选配丰富的插件,打造你得心应手的工具集合。”,体验了下,好用且强大&…...

Linux常用基础命令❀
文章目录❀ ❀ls命令 ❀cd命令 ❀pwd命令 ❀date命令 ❀创建、删除文件和目录命令 ❀alias命令 ❀复制、移动、重命名、查看(文件、目录)命令 ❀find查找、wc统计命令 ❀vi/vim命令 1、打开文件 2、工作模式 vi与vim的四个模式 进入编辑模式…...

SQL-进阶
mysql --local-infile -u root -pset global local_infile 1;load data local infile 目录 into able 表名 fields terminated by , lines terminated by \n;...

[Pytorch]卷积运算conv2d
文章目录 [Pytorch]卷积运算conv2d一.F.Conv2d二.nn.Conv2d三.nn.Conv2d的运算过程 [Pytorch]卷积运算conv2d 一.F.Conv2d torch.nn.functional.Conv2d()的详细参数: conv2d(input: Tensor, weight: Tensor, bias: Optional[Tensor]None, stride: Union[_int, _s…...

主流开源监控系统一览
减少故障有两个层面的意思,一个是做好常态预防,不让故障发生;另一个是如果故障发生,要能尽快止损,减少故障时长。而监控的典型作用,就是帮助我们发现及定位故障,这两个环节对于减少故障时长至关…...

爬虫原理详解及requests抓包工具用法介绍
文章目录 一、什么是爬虫?二、爬虫的分类三、网址的构成四、爬虫的基本步骤五、动态页面和静态页面六、伪装请求头七、requests库介绍1. 概念:2. 安装方式(使用镜像源):3. 基本使用:4. response对象对应的方…...

tinkerCAD案例:31. 3D 基元形状简介
tinkerCAD案例:31. 3D 基元形状简介 1 将一个想法从头脑带到现实世界是一次令人兴奋的冒险。在 Tinkercad 中,这将从一个新的设计开始。 在新设计中,简单的原始形状可以通过不同的方式组合成更复杂的形状。 在这个项目中,你将探索…...

Vue2基础一、快速入门
零、文章目录 Vue2基础一、快速入门 1、Vue 概念 (1)为什么学 前端必备技能 岗位多,绝大互联网公司都在使用Vue 提高开发效率 高薪必备技能(Vue2Vue3) (2)Vue是什么 **概念:…...
【POJ-3279】Fliptile(递推+搜索)
POJ-3279. Fliptile(递推搜索) Vjudge链接 题目描述 农场主约翰知道,一头智力得到满足的奶牛是一头快乐的奶牛,它会产更多的奶。他为奶牛安排了一项脑力活动,让它们摆弄一个 M N M N MN 的方格 ( 1 ≤ M ≤ 15 …...
522个matplotlib绘图案例,包含:折线图、散点图、条形图、饼图、直方图、3D图等,源码可直接运行!
文章目录 matplotlib介绍图表介绍折线图(Line Plot)散点图(Scatter Plot)条形图(Bar Plot)饼图(Pie Chart)直方图(Histogram)箱线图(Box Plot&…...

windows安装Elasticsearch8.9.0
官网解压安装好路径(非中文,无空格) 可参考 言之有李LAX csdn http://t.csdn.cn/S2oju本人使用jdk17 修改配置elasticsearch.yml xpack.security.enabled: false xpack.security.http.ssl:enabled: false直接点击bin\elasticsearch.bat…...

用Delphi编写一个通用视频转换工具,让视频格式转换变得更简单
用Delphi编写的简单视频格式转换程序,它使用TComboBox、TOpenDialog和TSaveDialog组件来选择转换格式、选择源视频文件和选择目标视频文件。程序还使用TEdit组件允许用户输入参数,然后将这些组件中的信息拼接成转换命令并在DOS窗口中运行它。 procedure…...
Kafka系列之:安装Know Streaming详细步骤
Kafka系列之:安装Know Streaming详细步骤 一、相关技术博客二、安装elasticsearch1.下载elasticsearch2.创建数据目录3.创建es用户4.修改最大文件数5.解压elasticsearch6.赋予es用户目录权限7.修改es配置8.切换es用户启动elasticsearch三、安装KnowStreaming1.下载KnowStreami…...

绝杀 GETPOST 嵌套的 JSON 参数
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,常用于Web应用程序中的数据传输。在HTTP数据包信息传递时,JSON扮演着非常正常的角色,因为它是一种通用的数据格式,可以被多种编程语言和应用程…...

Spring 项目过程及如何使用 Spring
文章目录 1.创建 Spring 项目步骤1.1 创建 Maven 项目1.2添加 Spring 框架支持1.3 添加启动项2.如何使用 Spring2.1 存储 Bean 对象2.1.1 创建 Bean对象2.1.2 将 Bean对象注册到容器中 2.2 获取并使用 Bean对象2.2.1 使用 ApplicationContext 获取对象2.2.2 使用 BeanFactory 获…...
CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型
CVPR 2025 | MIMO:支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题:MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者:Yanyuan Chen, Dexuan Xu, Yu Hu…...

css实现圆环展示百分比,根据值动态展示所占比例
代码如下 <view class""><view class"circle-chart"><view v-if"!!num" class"pie-item" :style"{background: conic-gradient(var(--one-color) 0%,#E9E6F1 ${num}%),}"></view><view v-else …...

shell脚本--常见案例
1、自动备份文件或目录 2、批量重命名文件 3、查找并删除指定名称的文件: 4、批量删除文件 5、查找并替换文件内容 6、批量创建文件 7、创建文件夹并移动文件 8、在文件夹中查找文件...
day52 ResNet18 CBAM
在深度学习的旅程中,我们不断探索如何提升模型的性能。今天,我将分享我在 ResNet18 模型中插入 CBAM(Convolutional Block Attention Module)模块,并采用分阶段微调策略的实践过程。通过这个过程,我不仅提升…...

DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI
前一阵子在百度 AI 开发者大会上,看到基于小智 AI DIY 玩具的演示,感觉有点意思,想着自己也来试试。 如果只是想烧录现成的固件,乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外,还提供了基于网页版的 ESP LA…...

从零实现STL哈希容器:unordered_map/unordered_set封装详解
本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说,直接开始吧! 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...
鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/
使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题:docker pull 失败 网络不同,需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...

ArcGIS Pro制作水平横向图例+多级标注
今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作:ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等(ArcGIS出图图例8大技巧),那这次我们看看ArcGIS Pro如何更加快捷的操作。…...
Redis的发布订阅模式与专业的 MQ(如 Kafka, RabbitMQ)相比,优缺点是什么?适用于哪些场景?
Redis 的发布订阅(Pub/Sub)模式与专业的 MQ(Message Queue)如 Kafka、RabbitMQ 进行比较,核心的权衡点在于:简单与速度 vs. 可靠与功能。 下面我们详细展开对比。 Redis Pub/Sub 的核心特点 它是一个发后…...

【 java 虚拟机知识 第一篇 】
目录 1.内存模型 1.1.JVM内存模型的介绍 1.2.堆和栈的区别 1.3.栈的存储细节 1.4.堆的部分 1.5.程序计数器的作用 1.6.方法区的内容 1.7.字符串池 1.8.引用类型 1.9.内存泄漏与内存溢出 1.10.会出现内存溢出的结构 1.内存模型 1.1.JVM内存模型的介绍 内存模型主要分…...