后端整理(集合框架、IO流、多线程)

news2024/9/20 18:01:36

1. 集合框架

Java集合类主要有两个根接口Collection和Map派生出来
在这里插入图片描述
Collection派生两个子接口

  1. List
    List代表了有序可重复集合,可以直接根据元素的索引进行访问
  2. Set
    Set代表无序不可重复集合,只能根据元素本身进行访问
    在这里插入图片描述
    Map接口派生
    Map代表的是存储key-value对的集合,可根据元素的key来访问value
    在这里插入图片描述

1.1 List

List集合特点:有索引,可重复,有序
扩容机制

  1. 初始值为10
  2. 如果数组的长度小于需要的最小容量则自动扩容
  3. 扩容到原来的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集合特点

  1. 键值对(key-value)映射关系
  2. 是单向的一对一关系,即一个键对应一个值
  3. 键不可重复,值可重复
  4. 无序

1.3.1 HashMap

HashMap的底层在jdk7及以前,是数组+链表;jdk8及以后,是数组+链表+红黑树
如何判断重复
先比较hashcode,若相同则使用equals比较插入的值,若值不同,则插入,若值不同,则不插入

2 IO流

IO流的体系
在这里插入图片描述
IO流的四大类

  • 字节输入流: 以内存为基准,把磁盘文件/网络中的数据以字节的形式读入到内存中去
  • 字节输出流: 以内存为基准,把内存中的数据以字节的形式写出到磁盘文件或网络中去
  • 字符输入流: 以内存为基准,来自磁盘文件/网络中的数据以字符的形式读入内存中
  • 字符输出流: 以内存为基准,把内存中的数据以字符的形式写出到磁盘文件或网络中去

2.1 IO流实现文件的上传下载

2.1.1 文件上传

文章引用IO流–文件上传实现(侵删)
文件上传,我们就需要的一个服务器和客户端,两者需要进行通信,两者通信的要素是服务器的IP地址和对应的端口号才能建立连接

  1. 首先开启服务器,并开启一个端口号给客户端进行连接通信
 serverSocket = new ServerSocket(port);
  1. 服务器通过监听端口来进行确定是否有客户端进行访问
socket = serverSocket.accept();
  1. 服务器准备完成,可以与客户端进行通信,首先客户端创立连接
 socket = new Socket(InetAddress.getByName(IP), port);
  1. 连接成功,然后通过IO流进行文件传输,先读取文件,再将文件转为IO流输出(读取是本地读取,输出是输出给服务端)
 //2.然后向服务器发送消息,需要一个输出流
            os = socket.getOutputStream();
 //3.读取本地的文件并输出,需要一个输入流
            is = new FileInputStream("123.txt");
  1. 客户端需要通过一个缓冲区来让文件实现完整的上传和输出,通过一个字节数组,保证整个文件不会因为字符数量的大小导致文件上传失败
   //4.读取文件中的内容并输出,读取文件的内容需要一个字节流,用字节数组来接收
            byte[] buffer = new byte[1024];//这个字节数组是属于IO流中的缓冲区,
            int length ;
            while ((length=is.read(buffer) )!= -1){
                os.write(buffer,0,length);
            }

  1. 到这一步,客户端的任务完成了大半,然后就是服务器端的接受操作,与客户端也是大同小异,通过文件字节输入流和文件字节输出流对连接中的数据进行读取和输出
      //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种线程的创建方法

  1. 继承Thread方法,实现run方法
  2. 实现Callable接口,重写call方法
  3. 实现Runnable接口,重写run方法
  4. 线程池构建线程

3.2 线程的状态

在这里插入图片描述

3.3 自定义线程池的核心参数

  1. 核心线程数
  2. 最大线程数
  3. 最大存活时间
  4. 最大存活时间单位
  5. 阻塞队列
  6. 线程工厂
  7. 拒绝策略

拒绝策略有四种:

  • 抛出异常
  • 把处理返回给调用者,谁调用谁处理
  • 直接拒绝
  • 清理掉最早的线程,再加入新建的线程

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 自旋锁

自旋锁是指线程在没有获得锁资源时不是直接挂起,而是执行一个忙循环,这个忙循环就是所谓的自旋
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/821038.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Vue2面试题

1. Vue 的基本原理 当 一 个 Vue 实 例 创 建 时 &#xff0c; Vue 会 遍 历 data 中 的 属 性 &#xff0c; 用 Object.defineProperty &#xff08; vue3.0 使 用 proxy&#xff09; 将 它 们 转 为 getter/setter&#xff0c;并且在内部追踪相关依赖&#xff0c;在属性被访…

linux系统中详细分析MMU的具体实现

先来看一张图 ​第一&#xff1a;MMU内存管理 MMU&#xff08;Memory Management Unit&#xff0c;内存管理单元&#xff09;是一种硬件模块&#xff0c;用于在CPU和内存之间实现虚拟内存管理。 其主要功能是将虚拟地址转换为物理地址&#xff0c;同时提供访问权限的控制和缓存…

控制反转ioc理解,配置说明

先写个例子吧 配置文件&#xff1a; <?xml version"1.0" encoding"UTF-8"?> <beans xmlns"http://www.springframework.org/schema/beans"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"h…

价值 1k 嵌入式面试题-单片机 main 函数之前都做了啥?

开门见山 请说下单片机&#xff08;Arm&#xff09;在运行到 main() 函数前&#xff0c;都做了哪些工作&#xff1f; 常见问题 系统初始化工作&#xff0c;太泛泛硬件初始化&#xff0c;比较不具体 答题思路 这道题应该从两方面回答&#xff0c;一个是比较表面的硬件的初始化…

leetcode(力扣) 剑指 Offer 12. 矩阵中的路径(回溯 DFS)

文章目录 题目描述思路分析完整代码 题目描述 给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 单词必须按照字母顺序&#xff0c;通过相邻的单元格内的字母构成&#xff…

不用这些网站,你哪来的时间摸鱼?

Postcat - 在线API 开发测试工具 postcat.com/ API 开发测试工具 Postcat 是一个强大的开源、免费的、跨平台&#xff08;Windows、Mac、Linux、Browsers...&#xff09;的 API 开发测试工具&#xff0c;支持 REST、Websocket 等协议&#xff08;即将支持 GraphQL、gRPC、TCP…

LLM - LLama 模型读取报错 TypeError: not a string

一.引言 读取 LLama2 模型时报错 TypeError: not a string 看异常栈是 AutoTokenizer.from_pretrained 时候的异常。 二.问题解决 出现类似加载模型异常的问题&#xff0c;大致分两类&#xff1a; ◆ 模型地址异常 脚本里传的 pretrained_model Path 有问题&#xff0c;加 …

Python 3.X环境下搭建Robot Framework过程及问题汇总

目录 一、基础RF环境搭建&#xff1a; 二、问题处理&#xff1a; Python 3.X环境下搭建Robot Framework过程 python3.X已经支持robot framework了&#xff0c;更新一版安装过程。总体来说安装过程简化了很多&#xff0c;但依然有一些小地方需要注意。 一、基础RF环境搭建&a…

【Redis深度专题】「核心技术提升」探究Redis服务启动的过程机制的技术原理和流程分析的指南(集群指令分析—上篇)

探究Redis服务启动的过程机制的技术原理和流程分析的指南&#xff08;Redis集群管理&#xff09; Redis集群管理查看集群中各个节点状态集群(cluster)cluster info的执行效果指令结果分析 cluster nodes的执行效果指令结果分析 节点(node)CLUSTER MEETCLUSTER FORGETCLUSTER RE…

python实现视频转GIF动图(无水印,包含代码详解和.exe执行文件)

该代码提供了一个简单的界面&#xff0c;允许用户将视频转换为GIF动画&#xff0c;并且可以自定义采样率、GIF帧率和输出大小。修改后的代码将视频帧的大小调整为固定的尺寸&#xff0c;并在生成GIF动画时保持这个尺寸。 一、核心代码实现 核心代码如下&#xff1a; import c…

数据挖掘实战:基于KMeans算法对超市客户进行聚类分群(文末送书)

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…

3 分钟全面了解 API Moke

一、什么是密闭服务&#xff1f; Google 测试团队的博客中&#xff0c;有一篇博文介绍的正是《Hermetic Servers&#xff08;密闭服务&#xff09;》。如下图所示&#xff0c;当被测试系统依赖了 Another Backend&#xff0c;这种依赖即产生了 “不可控” 因素。 怎么定义密闭…

ECharts:一款超实用的基于JavaScript的数据可视化图表库

一、ECharts的简单介绍 ECharts是一款基于JavaScript的数据可视化图表库&#xff0c;提供直观&#xff0c;生动&#xff0c;可交互&#xff0c;可个性化定制的数据可视化图表。ECharts最初由百度团队开源&#xff0c;并于2018年初捐赠给Apache基金会&#xff0c;成为ASF孵化级…

MapBox 做聚合图点位聚合效果实现教程

最近收到一个需求&#xff0c;要对 5000的点位进行展示。直接展示的话满屏幕都是点&#xff0c;效果太丑&#xff0c;于是想到了聚合&#xff0c;聚合有很多种方案。首先你可以手动的些代码来计算某个范围内的点的数量然后再把聚合的结果展示在这个范围的某个位置。这针对于简单…

使用java.io.BufferedReader的readLine()函数读入一行文本

说明 可以使用java.io.BufferedReader的readLine()函数读入一行文本&#xff0c;返回的字符串不包含回车和换行字符。 https://docs.oracle.com/en/java/javase/19/docs/api/java.base/java/io/BufferedReader.html#readLine() 代码示例 读取控制台的输入 使用下面的代码来验…

TSINGSEE青犀视频汇聚平台EasyCVR多种视频流播放协议介绍

众所周知&#xff0c;TSINGSEE青犀视频汇聚平台EasyCVR可支持多协议方式接入&#xff0c;包括主流标准协议GB28181、RTSP/Onvif、RTMP等&#xff0c;以及厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等。今天我们来说一说&#xff0c;EasyCVR平台支持分…

年度最强大模型顶会来袭!喊话中国数百万AI开发者,速来!

能硬核 生态共创”“产业共振 智能涌现”“产教融合 人才共育”“携手飞桨 创新加速”2023年全球AI浪潮迭起&#xff0c;大语言模型热度空前&#xff0c;生成式人工智能为千行百业高质量发展带来更多想象空间。作为前沿科技风向标、汇聚全球开发者的顶级盛会&#xff0c;WAVE S…

Java on VS Code 7 月更新|反编译器支持升级、代码补全性能提升、AI 相关更新及更多

作者&#xff1a;Nick Zhu 排版&#xff1a;Alan Wang 大家好&#xff0c;欢迎来到 Visual Studio Code for Java 的7月更新&#xff01;在这篇博客中&#xff0c;我们将为您提供有关反编译器支持的重要更新。此外&#xff0c;我们将分享更多最近代码补全性能提升的进展&#x…

B079-项目实战--支付模块 定时任务 项目总结

目录 概述示例jar包配置类任务详情 项目应用封装的工具类QuartzUtils封装IQuartzSrvice和QuartzServiceImpl封装参数QuartzJobInfo编写任务逻辑MainJob调用第三方支付前添加定时任务异步回调后移除定时任务 订单支付整体流程 概述 优势&#xff1a;Tmer不支持持久化&#xff0…

亚马逊水基灭火器UL8测试报告ISO17025实验室办理

在跨境电商平台上销售的境外电商&#xff0c;在美国市场中需要提供相关的安全规范报告。其中&#xff0c;美国相关部门要求&#xff0c;如果商家未能提交UL&#xff08;Underwriters Laboratories&#xff09;标准的检测报告&#xff0c;将会被责令停止销售。而为了在亚马逊、T…