后端整理(集合框架、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 获…...

信息学奥赛一本通——1258:【例9.2】数字金字塔
文章目录 题目【题目描述】【输入】【输出】【输入样例】【输出样例】 AC代码 题目 【题目描述】 观察下面的数字金字塔。写一个程序查找从最高点到底部任意处结束的路径,使路径经过数字的和最大。每一步可以从当前点走到左下方的点也可以到达右下方的点。 在上面…...

selenium官网文档阅读总结(day 2)
1.selenium元素定位方法 1.1selenium命令 当我们使用chormdriver打开网页后,接下来就要用python操作元素,模拟用户会作出的操作,这些操作元素的方法就是命令。比如 (1) click:点击(按钮,单选框ÿ…...

VMware虚拟机安装VMware tools
一、挂载光驱 执行以下命令来创建 /mnt/cdrom 目录: mkdir -p /mnt/cdrom-p 参数会确保如果 /mnt/cdrom 的上级目录(例如 /mnt)不存在的话也会被创建。 然后,你可以再次尝试挂载光盘: mount /dev/sr0 /mnt/cdrom这次…...

【Linux命令200例】rm用来删除文件或目录(谨慎使用)
🏆作者简介,黑夜开发者,全栈领域新星创作者✌,阿里云社区专家博主,2023年6月csdn上海赛道top4。 🏆本文已收录于专栏:Linux命令大全。 🏆本专栏我们会通过具体的系统的命令讲解加上鲜…...

行云管家荣获CFS第十二届财经峰会 “2023产品科技创新奖”
7月26日至27日,CFS第十二届财经峰会暨2023可持续商业大会在京盛大召开。峰会主题为“激活高质量发展澎湃活力”,超1000位政商领袖、专家学者、企业及媒体代表出席了本次盛会,共同分享新技术新产品新趋势、研判全球新挑战与新变局下企业的机遇…...

uniapp禁止页面滚动
用 touchmove.stop.prevent“moveHandle”,moveHandle 可以用来处理 touchmove 的事件,也可以是一个空函数。 <viewclass“mask” touchmove.stop.prevent“moveHandle”>...

ModuleNotFoundError: No module named ‘_sqlite3‘
前言 遇到报错信息如下: ModuleNotFoundError: No module named _sqlite3解决方式 参考解决方式: https://blog.csdn.net/jaket5219999/article/details/53512071 find / -name _sqlite*.socp /usr/lib64/python3.6/lib-dynload/_sqlite3.cpython-36…...

Rust的入门篇(下)
这篇博客是rust入门篇下 45. 生命周期注释 // 生命周期// 下面代码不能通过编译 // longer 函数取 s1 和 s2 两个字符串切片中较长的一个返回其引用值 // 返回值引用可能会返回过期的引用 // fn longer(s1: &str, s2: &str) -> &str { // if s2.len() >…...

PYTHON-logging-工具类-支持中文字符控制台输出和文件写入-不会导致乱码
import logging import sys import os import time from logging.handlers import RotatingFileHandler import iodef get_logger(tag):# 创建一个新的输出流,并指定编码为UTF-8sys.stdout io.TextIOWrapper(sys.stdout.buffer, encodingutf-8)accPath logsif not…...

对gpt的简单认识
1.gpt是什么? GPT(Generative Pre-trained Transformer 生成式预训练Transformer模型)是一种基于Transformer架构的预训练语言模型,由OpenAI开发。GPT模型以无监督学习的方式使用大规模语料库进行预训练,并具有生成文…...