【Java】留下没有基础眼泪的面试题

本文涉及的产品
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
容器服务 Serverless 版 ACK Serverless,317元额度 多规格
简介: 计算机/Java基础面试题

前言

只有光头才能变强

本文力求简单讲清每个知识点,希望大家看完能有所收获

一、如何减少线程上下文切换

使用多线程时,不是多线程能提升程序的执行速度,使用多线程是为了更好地利用CPU资源

程序在执行时,多线程是CPU通过给每个线程分配CPU时间片来实现的,时间片是CPU分配给每个线程执行的时间,因时间片非常短,所以CPU通过不停地切换线程执行

线程不是越多就越好的,因为线程上下文切换是有性能损耗的,在使用多线程的同时需要考虑如何减少上下文切换

一般来说有以下几条经验

  • 无锁并发编程。多线程竞争时,会引起上下文切换,所以多线程处理数据时,可以用一些办法来避免使用锁,如将数据的ID按照Hash取模分段,不同的线程处理不同段的数据
  • CAS算法。Java的Atomic包使用CAS算法来更新数据,而不需要加锁
  • 控制线程数量。避免创建不需要的线程,比如任务很少,但是创建了很多线程来处理,这样会造成大量线程都处于等待状态
  • 协程。在单线程里实现多任务的调度,并在单线程里维持多个任务间的切换

    • 协程可以看成是用户态自管理的“线程”不会参与CPU时间调度,没有均衡分配到时间。非抢占式

还可以考虑我们的应用是IO密集型的还是CPU密集型的。

  • 如果是IO密集型的话,线程可以多一些。
  • 如果是CPU密集型的话,线程不宜太多。

参考资料:

二、计算机网络

2.1MAC地址已经是唯一了,为什么需要IP地址?

或者可以反过来问:已经有IP地址了,为什么需要MAC地址??在zhihu上还蛮多类似的问题的:

我来简单总结一下为什么有了MAC(IP)还需要IP(MAC):

  • MAC是链路层,IP是网络层,每一层干每一层的事儿,之所以在网络上分链路层、网络层(...,就是将问题简单化。
  • 历史的兼容问题。

已经有IP地址了,为什么需要MAC地址??

  • 现阶段理由:DHCP基于MAC地址分配IP

MAC地址已经是唯一了,为什么需要IP地址?

  • MAC无网段概念,非类聚,不好管理

如果有更好的看法,不妨在评论区下留言哦~

参考资料:

2.2TCP状态

TCP 每个状态说一下,TIME-WAIT状态说一下

TCP总共有11个状态,状态之间的转换是这样的:

流程图:

下面我简单总结一下每个状态:

  • CLOSED:初始状态,表示TCP连接是“关闭着的”或“未打开的”。
  • LISTEN:表示服务器端的某个SOCKET处于监听状态,可以接受客户端的连接。
  • SYN-SENT:表示客户端已发送SYN报文。当客户端SOCKET执行connect()进行连接时,它首先发送SYN报文,然后随即进入到SYN_SENT状态。
  • SYN_RCVD:表示服务器接收到了来自客户端请求连接的SYN报文。当TCP连接处于此状态时,再收到客户端的ACK报文,它就会进入到ESTABLISHED状态
  • ESTABLISHED:表示TCP连接已经成功建立
  • FIN-WAIT-1第一次主动请求关闭连接,等待对方的ACK响应。
  • CLOSE_WAIT:对方发了一个FIN报文给自己,回应一个ACK报文给对方。此时进入CLOSE_WAIT状态。

    • 接下来呢,你需要检查自己是否还有数据要发送给对方,如果没有的话,那你也就可以close()这个SOCKET并发送FIN报文给对方,即关闭自己到对方这个方向的连接
  • FIN-WAIT-2:主动关闭端接到ACK后,就进入了FIN-WAIT-2。在这个状态下,应用程序还有接受数据的能力,但是已经无法发送数据。
  • LAST_ACK:当被动关闭的一方在发送FIN报文后,等待对方的ACK报文的时候,就处于LAST_ACK 状态
  • CLOSED:当收到对方的ACK报文后,也就可以进入到CLOSED状态了。
  • TIME_WAIT:表示收到了对方的FIN报文,并发送出了ACK报文。TIME_WAIT状态下的TCP连接会等待2*MSL
  • CLOSING:罕见的状态。表示双方都正在关闭SOCKET连接

TIME_WAIT状态一般用来处理以下两个问题:

  • 关闭TCP连接时,确保最后一个ACK正常运输(或者可以认为是:等待以便重传ACK)
  • 网络上可能会有残余的数据包,为了能够正常处理这些残余的数据包。使用TIME-WAIT状态可以确保创建新连接时,先前网络中残余的数据都丢失了

TIME_WAIT过多怎么解决?

如果在高并发,多短链接情景下,TIME_WAIT就会过多。

可以通过调整内核参数解决:vi /etc/sysctl.conf 加入以下内容设置:

  • reuse是表示是否允许重新应用处于TIME-WAIT状态的socket用于新的TCP连接;
  • recyse是加速TIME-WAIT sockets回收

我们可以知道TIME_WAIT状态是主动关闭连接的一方出现的,我们不要轻易去使用上边两个参数。先看看是不是可以重用TCP连接来尽量避免这个问题(比如我们HTTP的KeepAlive)~

参考资料:

2.3TCP滑动窗口

TCP是一个可靠的传输协议,它要保证所有的数据包都可以到达,这需要重传机制来支撑。

重传机制有以下几种:

  • 超时重传
  • 快速重传
  • SACK 方法

滑动窗口可以说是TCP非常重要的一个知识点。TCP的滑动窗口主要有两个作用:

  • 提供TCP的可靠性
  • 提供TCP的流控特性

简略滑动窗口示意图:

详细滑动窗口示意图:

  • 1已收到ack确认的数据。

  • 2发还没收到ack的。

  • 3在窗口中还没有发出的(接收方还有空间)。

  • 4窗口以外的数据(接收方没空间)

接受端控制发送端的图示:

2.4拥塞控制

TCP不是一个自私的协议,当拥塞发生的时候,要做自我牺牲。就像交通阻塞一样,每个车都应该把路让出来,而不要再去抢路了

拥塞控制主要是四个算法:

  • 1)慢启动,
  • 2)拥塞避免,
  • 3)拥塞发生,
  • 4)快速恢复

拥塞控制的作用:

拥塞的判断:

  • 重传定时器超时
  • 收到三个相同(重复)的 ACK

强烈建议阅读:

参考资料:

三、操作系统

3.1僵尸进程和孤儿进程是什么(区别)

unix/linux环境下

僵尸进程:

  • 父进程创建出子进程,子进程退出了,父进程没有调用waitwaitId获取子进程的信息(状态),子进程的描述符仍在系统中

孤儿进程:

  • 父进程退出,子进程仍在运行中。这些子进程就叫做孤儿进程,孤儿进程将被init进程(进程号为1)所收养,并由init进程对它们完成状态收集工作

僵尸进程危害

  • 系统进程表是一项有限资源,如果系统进程表被僵尸进程耗尽的话,系统就可能无法创建新的进程
  • 一个父进程创建了很多子进程,就是不回收,会造成内存资源的浪费

解决僵尸进程的手段:

  • 杀掉父进程,余下的僵尸进程会成为孤儿进程,最后被init进程管理
  • 子进程退出时向父进程发送SIGCHILD信号,父进程处理SIGCHILD信号。在信号处理函数中调用wait进行处理僵尸进程
  • fork两次:原理是将子进程成为孤儿进程,从而其的父进程变为init进程,通过init进程可以处理僵尸进程

参考资料:

3.2操作系统进程间通信的方式有哪些?

首先要知道的是:进程和线程的关注点是不一样的:

  • 进程间资源是独立的,关注的是通讯问题。
  • 线程间资源是共享的,关注的是安全问题。

操作系统进程间通信的方式有哪些?

  • 管道(pipe):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。
  • 有名管道(named pipe):有名管道也是半双工的通信方式,但是它允许无亲缘关系进程之间的通信。
  • 消息队列(message queue):消息队列是消息的链表,存放在内核中并由消息队列表示符标示。消息队列克服了信号传递信息少,管道只能承载无格式字节流以及缓冲区大小受限制等缺点。
  • 共享内存(shared memory):共享内存就是映射一段内被其它进程所访问的内存,共享内存由一个进程创建,但是多个进程都可以访问。共享内存是最快的IPC,它是针对其它进程通信方式运行效率低的而专门设计的。它往往与其它通信机制。如信号量,配合使用,来实现进程间的同步和通信。
  • 套接字(socket):套接字也是进程间的通信机制,与其它通信机制不同的是,它可以用于不同机器间的进程通信。
  • 信号(signal):信号是一种比较复杂的通信方式,用于通知接受进程进程某个时间已经发生。
  • 信号量(semaphore):信号量是一个计数器,可以用来控制多个进程对共享资源的访问。

    • 它常作为一种锁的机制,防止某进程正在访问共享资源时,其它进程也访问该资源。因此它主要作为不同进程或者同一进程之间不同线程之间同步的手段

3.3操作系统线程间通信的方式有哪些?

操作系统线程间通信的方式有哪些?(可以直接理解成:线程之间同步的方式有哪些)

  • 锁机制:包括互斥锁、条件变量、读写锁
  • 信号量机制(Semaphore):包括无名线程信号量和命名线程信号量
  • 信号机制(Signal):类似进程间的信号处理

线程间的通信目的主要是用于线程同步

参考资料:

扩展阅读:

3.4操作系统进程调度算法有哪些?

操作系统进程调度算法有哪些?

  • 先来先服务算法(FCFS)

    • 谁先来,就谁先执行
  • 短进程/作业优先算法(SJF)

    • 谁用的时间少、就先执行谁
  • 最高响应比优先算法(HRN)

    • 对FCFS方式和SJF方式的一种综合平衡
  • 最高优先数算法

    • 系统把处理机分配给就绪队列中优先数最高的进程
  • 基于时间片的轮转调度算法

    • 每个进程所享受的CPU处理时间都是一致的
  • 最短剩余时间优先算法

    • 短作业优先算法的升级版,只不过它是抢占式
  • 多级反馈排队算法

    • 设置多个就绪队列,分别赋予不同的优先级,如逐级降低,队列1的优先级最高

参考笔记:

四、拓展阅读

此部分是看别人的博文已经写得很好了,分享给大家~

4.1ConcurrentHashMap中的扩容是否需要对整个表上锁?

ConcurrentHashMap中的扩容是否需要对整个表上锁?

总结(摘抄)要点:

  • 通过给每个线程分配桶区间(默认一个线程分配的桶是16个),避免线程间的争用。
  • 通过为每个桶节点加锁,避免 putVal 方法导致数据不一致。
  • 同时,在扩容的时候,也会将链表拆成两份,这点和 HashMap 的 resize 方法类似。

参考资料:

4.2什么是一致性Hash算法(原理)?

什么是一致性Hash算法(原理)?

总结(摘抄)要点:

  • 一致性Hash算法将整个哈希值空间组织成一个虚拟的圆环,好处就是提高容错性和可扩展性

    • 对于节点的增减都只需重定位环空间中的一小部分数据

参考资料:

4.3MySQL date、datetime和timestamp类型的区别

MySQL date、datetime和timestamp类型的区别

总结(摘抄)要点:

  • date精确到天,datetime和timestamp精确到秒
  • datetime和timestamp的区别:

    • timestamp会跟随设置的时区变化而变化,而datetime保存的是绝对值不会变化
    • timestamp储存占用4个字节,datetime储存占用8个字节
    • 可表示的时间范围不同,timestamp只能到表示到2038年,datetime可到9999年

参考资料:

4.4判断一个链表是否有环/相交

判断一个链表是否有环(实际上就是看看有无遍历到重复的节点),解决方式(3种):

  1. for遍历两次
  2. 使用hashSet做缓存,记录已遍历过的节点
  3. 使用两个指针,一前一后遍历,总会出现前指针==后指针的情况

参考资料:


判断两个无环链表是否相交,解决方式(2种):

  • 将第一个链表尾部的next指针指向第二个链表,两个链表组成一个链表。

    • 判断这一个链表是否有环,有环则相交,无环则不相交
  • 直接判断两个链表的尾节点是否相等,如果相等则相交,否则不相交

判断两个有环链表是否相交(注:当一个链表中有环,一个链表中没有环时,两个链表必不相交):

  • 找到第一个链表的环点,然后将环断开(当然不要忘记了保存它的下一个节点),然后再来遍历第二个链表,如果发现第二个链表从有环变成了无环,那么他们就是相交的嘛,否则就是不相交的了。

参考资料:

4.5keepAlive含义

  • HTTP协议的Keep-Alive意图在于连接复用,同一个连接上串行方式传递请求-响应数据
  • TCP的KeepAlive机制意图在于保活、心跳,检测连接错误

参考资料:

最后

如果大家有更好的理解方式或者文章有错误的地方还请大家不吝在评论区留言,大家互相学习交流~~~

如果想看更多的原创技术文章,欢迎大家关注我的微信公众号:Java3y。Java技术群讨论:742919422。公众号还有海量的视频资源哦,关注即可免费领取。

可能感兴趣的链接:

相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
目录
相关文章
|
6天前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
20 2
|
11天前
|
存储 算法 Java
大厂面试高频:什么是自旋锁?Java 实现自旋锁的原理?
本文详解自旋锁的概念、优缺点、使用场景及Java实现。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
大厂面试高频:什么是自旋锁?Java 实现自旋锁的原理?
|
16天前
|
存储 缓存 Oracle
Java I/O流面试之道
NIO的出现在于提高IO的速度,它相比传统的输入/输出流速度更快。NIO通过管道Channel和缓冲器Buffer来处理数据,可以把管道当成一个矿藏,缓冲器就是矿藏里的卡车。程序通过管道里的缓冲器进行数据交互,而不直接处理数据。程序要么从缓冲器获取数据,要么输入数据到缓冲器。
Java I/O流面试之道
|
12天前
|
存储 缓存 Java
大厂面试必看!Java基本数据类型和包装类的那些坑
本文介绍了Java中的基本数据类型和包装类,包括整数类型、浮点数类型、字符类型和布尔类型。详细讲解了每种类型的特性和应用场景,并探讨了包装类的引入原因、装箱与拆箱机制以及缓存机制。最后总结了面试中常见的相关考点,帮助读者更好地理解和应对面试中的问题。
38 4
|
13天前
|
存储 Java 程序员
Java基础的灵魂——Object类方法详解(社招面试不踩坑)
本文介绍了Java中`Object`类的几个重要方法,包括`toString`、`equals`、`hashCode`、`finalize`、`clone`、`getClass`、`notify`和`wait`。这些方法是面试中的常考点,掌握它们有助于理解Java对象的行为和实现多线程编程。作者通过具体示例和应用场景,详细解析了每个方法的作用和重写技巧,帮助读者更好地应对面试和技术开发。
53 4
|
1月前
|
存储 安全 算法
Java面试题之Java集合面试题 50道(带答案)
这篇文章提供了50道Java集合框架的面试题及其答案,涵盖了集合的基础知识、底层数据结构、不同集合类的特点和用法,以及一些高级主题如并发集合的使用。
86 1
Java面试题之Java集合面试题 50道(带答案)
|
1月前
|
存储 缓存 Java
java基础:IO流 理论与代码示例(详解、idea设置统一utf-8编码问题)
这篇文章详细介绍了Java中的IO流,包括字符与字节的概念、编码格式、File类的使用、IO流的分类和原理,以及通过代码示例展示了各种流的应用,如节点流、处理流、缓存流、转换流、对象流和随机访问文件流。同时,还探讨了IDEA中设置项目编码格式的方法,以及如何处理序列化和反序列化问题。
67 1
java基础:IO流 理论与代码示例(详解、idea设置统一utf-8编码问题)
|
25天前
|
存储 Java 程序员
Java面试加分点!一文读懂HashMap底层实现与扩容机制
本文详细解析了Java中经典的HashMap数据结构,包括其底层实现、扩容机制、put和查找过程、哈希函数以及JDK 1.7与1.8的差异。通过数组、链表和红黑树的组合,HashMap实现了高效的键值对存储与检索。文章还介绍了HashMap在不同版本中的优化,帮助读者更好地理解和应用这一重要工具。
53 5
|
24天前
|
存储 Java
[Java]面试官:你对异常处理了解多少,例如,finally中可以有return吗?
本文介绍了Java中`try...catch...finally`语句的使用细节及返回值问题,并探讨了JDK1.7引入的`try...with...resources`新特性,强调了异常处理机制及资源自动关闭的优势。
19 1
|
1月前
|
Java 程序员
Java 面试高频考点:static 和 final 深度剖析
本文介绍了 Java 中的 `static` 和 `final` 关键字。`static` 修饰的属性和方法属于类而非对象,所有实例共享;`final` 用于变量、方法和类,确保其不可修改或继承。两者结合可用于定义常量。文章通过具体示例详细解析了它们的用法和应用场景。
28 3