Java高阶面试问答-通用基础

2023-11-13

线程和进程区别

  1. 进程是资源分配的最小单位,线程是程序执行的最小单位
  2. 进程有自己的独立地址空间,每启动一个进程,系统就会为它分配地址空间,建立数据表来维护代码段、堆栈段和数据段。线程是共享进程的数据空间,因此CPU切换一个线程的花费远比进程要小很多,同时创建一个线程的开销也比进程要小很多
  3. 线程之间的通信更方便,同一进程下的线程共享全局变量、静态变量等数据,而进程之间的通信需要以通信的方式(IPC)进行。不过如何处理好同步与互斥是编写多线程程序的难点。

硬链接与软链接的区别

每个文件都是创建了一个指针指向inode(代表物理硬盘的一个区块),可以通过ls -i查看。
硬链接是创建另一个文件,也通过创建指针指向inode。当你删除一个文件/硬链接时,它会删除一个到底层inode的指针。当inode的所有指针都被删除时,才会真正删除文件。
软连接是另外一种类型的文件,保存的是它指向文件的全路径,访问时会替换成绝对路径

查看某个进程中的线程

ps -T -p <pid>

查看某个文件夹中每个文件夹的大小

du --max-depth=1 -h

CPU负载的含义

一段时间内CPU正在处理和等待处理的进程总数与CPU最大处理进程数的比例。对于多核CPU来说最大LOAD是最大的核心数量。
使用toptop -Hp查找到CPU占用比较大的线程,进而使用jstack来排查Java程序的问题

快速排序

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-c27SjGc2-1677425171329)(null)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WGoneqkB-1677425171347)(null)]

首先任意选取一个数据(通常选用数组的第一个数)作为关键数据,然后将所有比它小的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一趟快速排序

最好情况:每次划分过程产生的区间大小都为n/2,一共需要划分log2n次,每次需要比较n-1次,O(nlog2n)
最坏情况:每次划分过程产生的两个区间分别包含n-1个元素和1个元素,一共需要划分n-1次,每次最多交换n-1次,这就是冒泡排序了,O(n2)

堆排序

  1. 根据初始数组去构造初始堆(构建一个完全二叉树,保证所有的父结点都比它的孩子结点数值大)。
  2. 每次交换第一个和最后一个元素,输出最后一个元素(最大值),然后把剩下元素重新调整为大根堆。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ziVlQu4b-1677425171285)(null)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EqJRQNy6-1677425171260)(null)]

堆排序过程的最好和最坏时间复杂度是O(nlog2n)

TOP K

如何在N个元素中寻找前K大的数?

快速排序:

  • 原理:每次快速排序中的划分过程能找到一个全部大于左边元素的一个值。如果该值的位置等于K,那么这个值和它左边的所有元素就是前K大的数;如果该值的位置小于K,那么对右边的元素继续划分排序;如果该值的位置大于K,那么对左边的元素继续划分排序
  • 问题:但空间复杂度是O(N),如果你要在很多元素中找很少几个top K的元素,或者在一个巨大的数据流里找到top K,快速排序是不合适的,堆排序更省地方

堆排序:

  • 原理:申请一个容量为K的数组,存入数组的前K个元素,创建长度为K的最小堆;从K开始循环数组的剩余元素,如果元素(a)比最小堆的根节点大,将a设置成最小堆的根节点,然后重建最小堆;循环完成后,最小堆中的所有元素就是需要找的最大的K个元素。
  • 优点:可以在N个元素中找到top K,时间复杂度是O(N log K),空间复杂的是O(K)

单例模式

  1. 懒汉(线程不安全,懒加载):如果没有实例就创建并返回,会有线程安全问题,简单加synchronized解决,但效率不高,升级版本是DCL
  2. 懒汉的升级DCL(线程安全,懒加载):加两个if是因为可能会有多个线程一起进入同步块外的if,如果在同步块内不进行二次检验的话就会生成多个实例了;instance = new Singleton()这句会有重排序的问题,用volidate解决
  3. 饿汉(线程安全,非懒加载):利用类加载器保证线程安全,但不是懒加载
  4. 饿汉升级静态内部类(线程安全,懒加载):在饿汉的基础上使用静态内部类解决非懒加载问题
  5. 枚举(线程安全,非懒加载):写法最简单,防止反序列化,但不是懒加载
    一般情况下直接使用饿汉式就好了,如果明确要求要懒加载会倾向于使用静态内部类,如果涉及到反序列化创建对象时会试着使用枚举的方式来实现单例。

状态模式

https://www.cnblogs.com/xyzq/p/11090344.html

装饰器模式

在保持原有功能接口不变的基础上动态扩展功能的模式。
Java IO包中就使用了该模式,InputStream有太多的实现类如FileInputStream,如果要在每个实现类上加上几种功能如缓冲区读写功能Buffered,则会导致出现ileInputStreamBuffered, StringInputStreamBuffered等等,如果还要加个按行读写的功能,类会更多,代码重复度也太高,你说改原来的接口也行啊,但是这样就是改变接口的内容了,现在我想做到不更改以前的功能,动态地增强原有接口。
所以使用FilterInputStream这个抽象装饰器来装饰InputStream,使得我们可以用BufferedInputStream来包装FileInputStream得到特定增强版InputStream,且增加装饰器种类也会更加灵活。

缺点:
会引入很多小类,从而增加使用复杂度,多层装饰的时候很容易导致不知道如何使用

在这里插入图片描述

策略模式

一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。在策略模式中,我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的 context 对象。策略对象改变 context 对象的执行算法。

比如利用策略模式优化过多 if else 代码,将这些if else算法封装成一个一个的类,任意地替换

在这里插入图片描述

整体思路如下:

  1. 定义一个 InnerCommand 接口,其中有一个 process 函数交给具体的业务实现。
  2. 根据自己的业务,会有多个类实现 InnerCommand 接口;这些实现类都会注册到 Spring Bean 容器中供之后使用。
  3. 通过客户端输入命令,从 Spring Bean 容器中获取一个 InnerCommand 实例。
  4. 执行最终的 process 函数。

缺点:

  1. 策略类会增多
  2. 所有策略类都需要对外暴露。

观察者模式

当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知它的依赖对象。定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

在这里插入图片描述

观察者模式使用三个类 Subject、Observer 和 Client。Subject 对象带有绑定观察者到 Client 对象和从 Client 对象解绑观察者的方法。我们创建 Subject 类、Observer 抽象类和扩展了抽象类 Observer 的实体类。

缺点:

  1. 如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间
  2. 如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃
  3. 观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化

TCP/IP

OSI是一个理论上的七层网络通信模型,而TCP/IP则是实际运行的四层网络协议。TCP/IP包含:

  1. 网络接口层,主机必须使用某种协议与网络相连
  2. 网络层,使主机可以把分组发往任何网络,并使分组独立地传向目标。IP协议
  3. 传输层,使源端和目的端机器上的对等实体可以进行会话。TCP和UDP协议
  4. 应用层,包含所有的高层协议,FTP/TELNET/SMTP/DNS/NNTP/HTTP

HTTP

HTTP是TCP/IP协议中的【应用层】协议。它不涉及数据包传输,主要规定了客户端和服务器之间的通信格式,是互联网信息交互中最常用的协议

特点:

  1. 简单快速。只需要传【请求方法】与【资源路径】就能确定资源
  2. 灵活,传输【任意类型】的数据
  3. 无连接,一般一次连接只处理一个请求,结束后主动释放连接,但在HTTP1.1中可以使用keep-alive来复用相同的TCP连接发送多个请求
  4. 无状态,客户端向服务器发送HTTP请求之后,服务器会给我们发送数据过来,但不会记录任何信息。所以Cookie、Session产生了。

TCP

TCP是一种面向连接的、可靠的、基于字节流的TCP/IP协议中的【传输层】协议

在这里插入图片描述

建立连接:三次握手

  1. 建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SENT状态,等待服务器确认;SYN:同步序列编号(Synchronize Sequence Numbers)。
  2. 服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;
  3. 客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手。

为什么要采用三次握手,两次不行吗

避免由于网络延迟导致的创建无效连接的问题。比如客户端发出的一个连接请求没有丢失,而是长时间在某个网络节点滞留了,以至于到连接释放之后才到达服务端,如果不使用三次握手,一旦服务端发出请求连接就会建立连接,但是这个连接请求已经失效了,则会浪费服务端的资源。

关闭连接:四次挥手

  1. 当主机A的应用程序通知TCP数据已经发送完毕时,TCP向主机B发送一个带有FIN附加标记的报文段(FIN表示英文finish)。
  2. 主机B收到这个FIN报文段之后,并不立即用FIN报文段回复主机A,而是先向主机A发送一个确认序号ACK,同时通知自己相应的应用程序:对方要求关闭连接(先发送ACK的目的是为了防止在这段时间内,对方重传FIN报文段)。
  3. 主机B的应用程序告诉TCP:我要彻底的关闭连接,TCP向主机A送一个FIN报文段。
  4. 主机A收到这个FIN报文段后,向主机B发送一个ACK表示连接彻底释放。

为什么连接的时候是三次握手,关闭的时候却是四次握手

因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,“你发的FIN报文我收到了”。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手。

滑动窗口协议

滑动窗口协议是传输层进行流控的一种措施,接收方通过通告发送方自己的窗口大小,从而控制发送方的发送速度,从而达到防止发送方发送速度过快而导致自己被淹没的目的。

ACK包含两个非常重要的信息:一是期望接收到的下一字节的序号n,该n代表接收方已经接收到了前n-1字节数据。二是当前的窗口大小m,如此发送方在接收到ACK包含的这两个数据后就可以计算出还可以发送多少字节的数据给对方,这就是滑动窗口控制流量的基本原理

TCP的滑动窗口是动态的,应用程序在需要(如内存不足)时,通过API通知TCP协议栈缩小TCP的接收窗口。然后TCP协议栈在下个段发送时包含新的窗口大小通知给对端,对端按通知的窗口来改变发送窗口,以此达到减缓发送速率的目的。

与UDP区别

  • TCP提供面向连接的、可靠的数据流传输,而UDP提供的是非面向连接的、不可靠的数据流传输,如QQ
  • TCP注重数据安全性,UDP数据传输快,因为不需要连接等待,少了许多操作,但是其安全性却一般
  • TCP对应的协议(FTP/SMTP/HTTP),UDP(DNS)

HTTPS

HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,要比http协议安全,可防止数据在传输过程中被窃取、改变,确保数据的完整性,它大幅增加了中间人攻击的成本。

加密过程:

  1. Hello - 握手开始于客户端发送Hello消息。包含服务端为了通过SSL连接到客户端的所有信息,包括客户端支持的各种密码套件和最大SSL版本。服务器也返回一个Hello消息,包含客户端需要的类似信息,包括到底使用哪一个加密算法和SSL版本。
  2. 证书交换 - 现在连接建立起来了,服务器必须通过SSL证书证明他的身份。SSL证书包含各种数据,包含所有者名称,相关属性(域名),证书上的公钥,数字签名和关于证书有效期的信息。客户端检查它是不是被CA验证过的且根据数字签名验证内容是否被修改过。注意服务器被允许需求一个证书去证明客户端的身份,但是这个只发生在敏感应用。
  3. 密钥交换 - 使用RSA非对称公钥加密算法(客户端生成一个对称密钥,然后用SSL证书里带的服务器公钥将该对称密钥加密。随后发送到服务端,服务端用服务器私钥解密,到此,握手阶段完成。)或者DH交换算法在客户端与服务端双方确定将要使用的密钥。这个密钥是双方都同意的一个简单,对称的密钥。这个过程是基于非对称加密方式和服务器的公钥/私钥的。
  4. 加密通信 - 在服务器和客户端加密实际信息是用到对称加密算法,用哪个算法在Hello阶段已经确定。对称加密算法是对于加密和解密都很简单的密钥。这个密钥是基于第三步在客户端与服务端已经商议好的。与需要公钥/私钥的非对称加密算法相反。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java高阶面试问答-通用基础 的相关文章

随机推荐

  • 软件工程——结构化分析:一种自上而下的分析方法(包含习题)

    什么是结构化分析 数据流图 数据字典 功能分解结构图 过程描述 结构化分析的优势与挑战 结合不同方法以适应不同场景 总结 习题1 银行计算机储蓄系统 习题2 机票预定系统 习题3 患者监护系统 习题4 复印机的状态转换图绘制 习题5 高校计
  • 一文详解分布式系统的分区

    为什么要分区 数据的复制是冗余的过程 冗余会增加可用性 并且可以有效均衡读取负载 而数据的分区是一个整体转换为局部的过程 这种拆解就像你拥有大量图书 但你的书架放不下 所以需要再加几个书架存储是一个道理 将整体拆分 局部存储在多个较小空间内
  • spring中创建bean的方式

    一 常见的bean创建方式 1 基于xml配置bean 2 使用 Component派生注解 3 使用 Configuration和 Bean注解 1 常见的使用xml中setter方法创建bean bean xml文件中配置bean时 加
  • 史上最全的OpenCV入门教程

    一 Python OpenCV 入门 欢迎阅读系列教程 内容涵盖 OpenCV 它是一个图像和视频处理库 包含 C C Python 和 Java 的绑定 OpenCV 用于各种图像和视频分析 如面部识别和检测 车牌阅读 照片编辑 高级机器
  • JS实现奇偶数的判断

    奇数和偶数的判断是数学运算中经常碰到的问题 比如 有变量x 如果x 1则为奇数 为2则为偶数 这篇文章主要讲解通过JavaScript来实现奇偶数的判断 方法一 求余 if else的形式 var num parseInt prompt 请
  • 人物专访

    把算法应用到各行各业中 这是我从创业初期就有的梦想 华院计算创始人 董事长宣晓华表示 文 科创板日报 黄心怡 成立于2002年的华院计算 可谓国内算法和AI的最早探索者之一 多年来始终致力于算法技术的研究和应用 面对当前的大模型浪潮 宣晓华
  • keyshot保存为ksp_keyshot渲染教程:keyshot教你如何简单的渲染冰与水

    摘要 keyshot是一个互动性的光线追踪与全域光渲染程序 keyshot的渲染的教程有哪些呢 下面是小编整理的关于keyshot渲染教程之keyshot教你如何简单的渲染冰与水 keyshot是一个互动性的光线追踪与全域光渲染程序 key
  • Windows解决camelot报错OSError: Ghostscript is not installed

    文章目录 解决方案 1 安装并配置Ghostscript 2 添加环境变量 3 重启python应用 解决方法也很简单 就是安装并配置Ghostscript 解决方案 1 安装并配置Ghostscript 首先访问 https ghosts
  • LeetCode--初级算法--数组篇-存在重复

    题目 给定一个整数数组 判断是否存在重复元素 如果任何值在数组中出现至少两次 函数返回 true 如果数组中每个元素都不相同 则返回 false 示例 1 输入 1 2 3 1 输出 true 示例 2 输入 1 2 3 4 输出 fals
  • 我是如何在12周内由零基础成为一名程序员的(转)

    我是如何在12周内由零基础成为一名程序员的 我的故事 在海军陆战队服役超过10年后 我于去年7月份退役了 随后在8月份找到了一份赌场的工作做公关 到今年2月中旬的时候又被辞退了 到5月中旬的时候我在DE协会找到了一份临时的 初级用户体验工程
  • Redis持久化的原理及优化

    更多内容 欢迎关注微信公众号 全菜工程师小辉 Redis提供了将数据定期自动持久化至硬盘的能力 包括RDB和AOF两种方案 两种方案分别有其长处和短板 可以配合起来同时运行 确保数据的稳定性 RDB 保存数据快照至一个RDB文件中 用于持久
  • An HTTP error occurred when trying to retrieve this URL.

    问题背景 conda install xxx 提示 An HTTP error occurred when trying to retrieve this URL Fetching package metadata CondaHTTPErr
  • 【Leetcode】863. 二叉树中所有距离为 K 的结点

    题目描述 题解 用map记录每个结点的父结点 然后让dfs从target结点开始 假设target就是根结点 然后递归时纪录深度 只要深度等于k 就是和target的距离等于k 就可以存入list 执行用时 14 ms 在所有 Java 提
  • LeetCode-1304. Find N Unique Integers Sum up to Zero

    Given an integer n return any array containing n unique integers such that they add up to 0 Example 1 Input n 5 Output 7
  • 毕业遭失业,前途一片黑暗...不得已转行软件测试,太多心酸和无助...

    大家好 我叫小涵 一名应届毕业生 目前已经成功转行互联网 写这篇文章的目的是因为很多人不喜欢自己的现状 想通过学习改变 奈何没有出路 所以想为这部分人提供一些思路 其次文章会总结我自己转行前后的经历和思考 提供一些我亲测有效的面试资源 找不
  • 解决Vmware Unbuntu 22虚拟机网络故障问题

    上午启动Vmware Unbuntu 22虚拟机 发现不能上网 屏幕右上侧的网络图标没有显示 怀疑是昨天在虚拟机上做路由器功能设置的时候某个操作产生的问题 于是进行排障 先尝试重启网络服务 service NetworkManager re
  • elasticsearch安装 及 启动异常解决

    虚拟机使用net连接模式 1 Download and unzip the latest Elasticsearch distribution 2 Run bin elasticsearch on Unix or bin elasticse
  • 第14课 右值引用(1)_基本概念

    1 左值和右值 1 两者区别 左值 能对表达式取地址 或具名对象 变量 一般指表达式结束后依然存在的持久对象 右值 不能对表达式取地址 或匿名对象 一般指表达式结束就不再存在的临时对象 2 右值的分类 将亡值 xvalue eXpiring
  • 数据中台-让数据用起来-7

    文章目录 第七章 数据体系建设 7 1 数体系规划 7 2 贴源数据层建设 全域数据统一存储 7 2 1 相关概念 7 2 2 贴源数据表设计 7 2 3 贴源数据表实现 7 3统一数仓层建设 标准化的数据底座 7 3 1 相关概念 7 3
  • Java高阶面试问答-通用基础

    线程和进程区别 进程是资源分配的最小单位 线程是程序执行的最小单位 进程有自己的独立地址空间 每启动一个进程 系统就会为它分配地址空间 建立数据表来维护代码段 堆栈段和数据段 线程是共享进程的数据空间 因此CPU切换一个线程的花费远比进程要