后端整理(集合框架、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 获…...
盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来
一、破局:PCB行业的时代之问 在数字经济蓬勃发展的浪潮中,PCB(印制电路板)作为 “电子产品之母”,其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透,PCB行业面临着前所未有的挑战与机遇。产品迭代…...
土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等
🔍 土地利用/土地覆盖数据是生态、环境和气象等诸多领域模型的关键输入参数。通过遥感影像解译技术,可以精准获取历史或当前任何一个区域的土地利用/土地覆盖情况。这些数据不仅能够用于评估区域生态环境的变化趋势,还能有效评价重大生态工程…...
UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)
UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中,UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化…...
html-<abbr> 缩写或首字母缩略词
定义与作用 <abbr> 标签用于表示缩写或首字母缩略词,它可以帮助用户更好地理解缩写的含义,尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时,会显示一个提示框。 示例&#x…...
算法:模拟
1.替换所有的问号 1576. 替换所有的问号 - 力扣(LeetCode) 遍历字符串:通过外层循环逐一检查每个字符。遇到 ? 时处理: 内层循环遍历小写字母(a 到 z)。对每个字母检查是否满足: 与…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...
【笔记】WSL 中 Rust 安装与测试完整记录
#工作记录 WSL 中 Rust 安装与测试完整记录 1. 运行环境 系统:Ubuntu 24.04 LTS (WSL2)架构:x86_64 (GNU/Linux)Rust 版本:rustc 1.87.0 (2025-05-09)Cargo 版本:cargo 1.87.0 (2025-05-06) 2. 安装 Rust 2.1 使用 Rust 官方安…...
C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)
名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...
通过 Ansible 在 Windows 2022 上安装 IIS Web 服务器
拓扑结构 这是一个用于通过 Ansible 部署 IIS Web 服务器的实验室拓扑。 前提条件: 在被管理的节点上安装WinRm 准备一张自签名的证书 开放防火墙入站tcp 5985 5986端口 准备自签名证书 PS C:\Users\azureuser> $cert New-SelfSignedCertificate -DnsName &…...
LOOI机器人的技术实现解析:从手势识别到边缘检测
LOOI机器人作为一款创新的AI硬件产品,通过将智能手机转变为具有情感交互能力的桌面机器人,展示了前沿AI技术与传统硬件设计的完美结合。作为AI与玩具领域的专家,我将全面解析LOOI的技术实现架构,特别是其手势识别、物体识别和环境…...
