Java常见面试题总结

文章目录

  • 1. 什么是线程和进程?
  • 2. 请简要描述线程与进程的关系,区别及优缺点?
  • 3. 什么是堆和方法区?
  • 4. 并发与并行的区别
  • 5. 同步和异步的区别
  • 6.为什么要使用多线程? 优点?(重要)
  • 7. 使用多线程可能带来什么问题?
  • 8. 如何理解线程安全和不安全?
  • 9. 单核 CPU 上运行多个线程效率一定会高吗?
  • 10. 如何创建线程?(重要)
  • 11. 说说线程的生命周期和状态?(重点)
  • 12. 什么是线程上下文切换?
  • 13. 什么是线程死锁?如何避免死锁?
  • 14. 可以直接调用 Thread 类的 run 方法吗?
  • 15. 乐观锁和悲观锁
  • 16. synchronized 关键字
  • 17. 共享锁和独占锁有什么区别?
  • 18. StringBuilder和StringBuffer区别(重要)
  • 19. MAP(重要)
    • 19.1 HashMap 和 Hashtable 的区别
    • 19.2 HashMap 的底层实现
  • 20. ArrayList 和 LinkedList 的区别 (重要)

1. 什么是线程和进程?

  • 何为进程?
    进程是程序的一次执行过程,是系统运行程序的基本单位,因此进程是动态的。系统运行一个程序即是一个进程从创建,运行到消亡的过程。
  • 何为线程?
    线程与进程相似,但线程是一个比进程更小的执行单位。一个进程在其执行的过程中可以产生多个线程。与进程不同的是同类的多个线程共享进程的堆和方法区资源,但每个线程有自己的程序计数器、虚拟机栈和本地方法栈,所以系统在产生一个线程,或是在各个线程之间做切换工作时,负担要比进程小得多,也正因为如此,线程也被称为轻量级进程。

2. 请简要描述线程与进程的关系,区别及优缺点?

线程是进程划分成的更小的运行单位。线程和进程最大的不同在于基本上各进程是独立的,而各线程则不一定,因为同一进程中的线程极有可能会相互影响。线程执行开销小,但不利于资源的管理和保护;而进程正相反。

3. 什么是堆和方法区?

堆和方法区是所有线程共享的资源,其中堆是进程中最大的一块内存,主要用于存放新创建的对象 (几乎所有对象都在这里分配内存),方法区主要用于存放已被加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。

4. 并发与并行的区别

  • 并发:两个及两个以上的作业在同一 时间段 内执行。
  • 并行:两个及两个以上的作业在同一 时刻 执行。

最关键的点是:是否是 同时 执行。

5. 同步和异步的区别

  • 同步:发出一个调用之后,在没有得到结果之前, 该调用就不可以返回,一直等待。
  • 异步:调用在发出之后,不用等待返回结果,该调用直接返回。

6.为什么要使用多线程? 优点?(重要)

先从总体上来说:

  • 从计算机底层来说: 线程可以比作是轻量级的进程,是程序执行的最小单位,线程间的切换和调度的成本远远小于进程。另外,多核 CPU 时代意味着多个线程可以同时运行,这减少了线程上下文切换的开销。
  • 从当代互联网发展趋势来说: 现在的系统动不动就要求百万级甚至千万级的并发量,而多线程并发编程正是开发高并发系统的基础,利用好多线程机制可以大大提高系统整体的并发能力以及性能。

再深入到计算机底层来探讨:

  • 单核时代:在单核时代多线程主要是为了提高单进程利用 CPU 和 IO 系统的效率。 假设只运行了一个 Java 进程的情况,当我们请求 IO 的时候,如果 Java 进程中只有一个线程,此线程被 IO 阻塞则整个进程被阻塞。CPU 和 IO 设备只有一个在运行,那么可以简单地说系统整体效率只有 50%。当使用多线程的时候,一个线程被 IO 阻塞,其他线程还可以继续使用 CPU。从而提高了 Java 进程利用系统资源的整体效率。
  • 多核时代: 多核时代多线程主要是为了提高进程利用多核 CPU 的能力。举个例子:假如我们要计算一个复杂的任务,我们只用一个线程的话,不论系统有几个 CPU 核心,都只会有一个 CPU 核心被利用到。而创建多个线程,这些线程可以被映射到底层多个 CPU 上执行,在任务中的多个线程没有资源竞争的情况下,任务执行的效率会有显著性的提高,约等于(单核时执行时间/CPU 核心数)。

7. 使用多线程可能带来什么问题?

并发编程的目的就是为了能提高程序的执行效率进而提高程序的运行速度,但是并发编程并不总是能提高程序运行速度的,而且并发编程可能会遇到很多问题,比如:内存泄漏、死锁、线程不安全等等。

8. 如何理解线程安全和不安全?

线程安全和不安全是在多线程环境下对于同一份数据的访问是否能够保证其正确性和一致性的描述。

  • 线程安全指的是在多线程环境下,对于同一份数据,不管有多少个线程同时访问,都能保证这份数据的正确性和一致性。
  • 线程不安全则表示在多线程环境下,对于同一份数据,多个线程同时访问时可能会导致数据混乱、错误或者丢失。

9. 单核 CPU 上运行多个线程效率一定会高吗?

单核 CPU 同时运行多个线程的效率是否会高,取决于线程的类型和任务的性质。一般来说,有两种类型的线程:CPU 密集型和 IO 密集型。CPU 密集型的线程主要进行计算和逻辑处理,需要占用大量的 CPU 资源。IO 密集型的线程主要进行输入输出操作,如读写文件、网络通信等,需要等待 IO 设备的响应,而不占用太多的 CPU 资源。

在单核 CPU 上,同一时刻只能有一个线程在运行,其他线程需要等待 CPU 的时间片分配。如果线程是 CPU 密集型的,那么多个线程同时运行会导致频繁的线程切换,增加了系统的开销,降低了效率。如果线程是 IO 密集型的,那么多个线程同时运行可以利用 CPU 在等待 IO 时的空闲时间,提高了效率。

因此,对于单核 CPU 来说,如果任务是 CPU 密集型的,那么开很多线程会影响效率;如果任务是 IO 密集型的,那么开很多线程会提高效率。当然,这里的“很多”也要适度,不能超过系统能够承受的上限。

10. 如何创建线程?(重要)

一般来说,创建线程有很多种方式,例如继承Thread类、实现Runnable接口、实现Callable接口、使用线程池、使用CompletableFuture类等等。

不过,这些方式其实并没有真正创建出线程。准确点来说,这些都属于是在 Java 代码中使用多线程的方法。

严格来说,Java 就只有一种方式可以创建线程,那就是通过new Thread().start()创建。不管是哪种方式,最终还是依赖于new Thread().start()。

11. 说说线程的生命周期和状态?(重点)

Java 线程在运行的生命周期中的指定时刻只可能处于下面 6 种不同状态的其中一个状态:

  • NEW: 初始状态,线程被创建出来但没有被调用 start() 。
  • RUNNABLE: 运行状态,线程被调用了 start()等待运行的状态。
  • BLOCKED:阻塞状态,需要等待锁释放。
  • WAITING:等待状态,表示该线程需要等待其他线程做出一些特定动作(通知或中断)。
  • TIME_WAITING:超时等待状态,可以在指定的时间后自行返回而不是像 WAITING 那样一直等待。
  • TERMINATED:终止状态,表示该线程已经运行完毕。
    在这里插入图片描述
    在这里插入图片描述

12. 什么是线程上下文切换?

线程在执行过程中会有自己的运行条件和状态(也称上下文),比如上文所说到过的程序计数器,栈信息等。当出现如下情况的时候,线程会从占用 CPU 状态中退出。

  • 主动让出 CPU,比如调用了 sleep(), wait() 等。
  • 时间片用完,因为操作系统要防止一个线程或者进程长时间占用 CPU 导致其他线程或者进程饿死。
  • 调用了阻塞类型的系统中断,比如请求 IO,线程被阻塞。
  • 被终止或结束运行

这其中前三种都会发生线程切换,线程切换意味着需要保存当前线程的上下文,留待线程下次占用 CPU 的时候恢复现场。并加载下一个将要占用 CPU 的线程上下文。这就是所谓的 上下文切换。

上下文切换是现代操作系统的基本功能,因其每次需要保存信息恢复信息,这将会占用 CPU,内存等系统资源进行处理,也就意味着效率会有一定损耗,如果频繁切换就会造成整体效率低下。

13. 什么是线程死锁?如何避免死锁?

线程死锁是多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放。由于线程被无限期地阻塞,因此程序不可能正常终止。

  1. 如何预防死锁?
    破坏死锁的产生的必要条件即可:
  • 破坏请求与保持条件:一次性申请所有的资源。
  • 破坏不剥夺条件:占用部分资源的线程进一步申请其他资源时,如果申请不到,可以主动释放它占有的资源。
  • 破坏循环等待条件:靠按序申请资源来预防。按某一顺序申请资源,释放资源则反序释放。破坏循环等待条件。
  1. 如何避免死锁?

    避免死锁就是在资源分配时,借助于算法(比如银行家算法)对资源分配进行计算评估,使其进入安全状态。

14. 可以直接调用 Thread 类的 run 方法吗?

new 一个 Thread,线程进入了新建状态。调用 start()方法,会启动一个线程并使线程进入了就绪状态,当分配到时间片后就可以开始运行了。 start() 会执行线程的相应准备工作,然后自动执行 run() 方法的内容,这是真正的多线程工作。 但是,直接执行 run() 方法,会把 run() 方法当成一个 main 线程下的普通方法去执行,并不会在某个线程中执行它,所以这并不是多线程工作。

需要重写run()方法实现多线程

15. 乐观锁和悲观锁

  1. 什么是悲观锁?

    悲观锁总是假设最坏的情况,认为共享资源每次被访问的时候就会出现问题(比如共享数据被修改),所以每次在获取资源操作的时候都会上锁,这样其他线程想拿到这个资源就会阻塞直到锁被上一个持有者释放。也就是说,共享资源每次只给一个线程使用,其它线程阻塞,用完后再把资源转让给其它线程。

  2. 什么是乐观锁?

    乐观锁总是假设最好的情况,认为共享资源每次被访问的时候不会出现问题,线程可以不停地执行,无需加锁也无需等待,只是在提交修改的时候去验证对应的资源(也就是数据)是否被其它线程修改了(具体方法可以使用版本号机制或 CAS 算法)。

理论上来说:

  • 悲观锁通常多用于写比较多的情况(多写场景,竞争激烈),这样可以避免频繁失败和重试影响性能,悲观锁的开销是固定的。不过,如果乐观锁解决了频繁失败和重试这个问题的话(比如LongAdder),也是可以考虑使用乐观锁的,要视实际情况而定。
  • 乐观锁通常多用于写比较少的情况(多读场景,竞争较少),这样可以避免频繁加锁影响性能。不过,乐观锁主要针对的对象是单个共享变量。

16. synchronized 关键字

  1. synchronized 是什么?有什么用?
    synchronized 是 Java 中的一个关键字,翻译成中文是同步的意思,主要解决的是多个线程之间访问资源的同步性,可以保证被它修饰的方法或者代码块在任意时刻只能有一个线程执行。

17. 共享锁和独占锁有什么区别?

共享锁:一把锁可以被多个线程同时获得。
独占锁:一把锁只能被一个线程获得。

18. StringBuilder和StringBuffer区别(重要)

a. 相同点:

用法一样,作用一样

b. 不同点:

StringBuilder:拼接效率比StringBuffer高,线程不安全

StringBuffer:效率比较底,线程安全

拼接效率:StringBuilder>StringBuffer>String

19. MAP(重要)

19.1 HashMap 和 Hashtable 的区别

  • 线程是否安全: HashMap 是非线程安全的,Hashtable 是线程安全的,因为 Hashtable 内部的方法基本都经过synchronized 修饰。
  • 效率: 因为线程安全的问题,HashMap 要比 Hashtable 效率高一点。另外,Hashtable 基本被淘汰,不要在代码中使用它
  • 对 Null key 和 Null value 的支持: HashMap 可以存储 null 的 key 和 value,但 null 作为键只能有一个,null 作为值可以有多个;Hashtable 不允许有 null 键和 null 值,否则会抛出 NullPointerException。
  • 初始容量大小和每次扩充容量大小的不同: ① 创建时如果不指定容量初始值,Hashtable 默认的初始大小为 11,之后每次扩充,容量变为原来的 2n+1。HashMap 默认的初始化大小为 16。之后每次扩充,容量变为原来的 2 倍。② 创建时如果给定了容量初始值,那么 Hashtable 会直接使用你给定的大小,而 HashMap 会将其扩充为 2 的幂次方大小。也就是说 HashMap 总是使用 2 的幂作为哈希表的大小。
  • 底层数据结构: JDK1.8 以后的 HashMap 在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为 8)时,将链表转化为红黑树(将链表转换成红黑树前会判断,如果当前数组的长度小于 64,那么会选择先进行数组扩容,而不是转换为红黑树),以减少搜索时间(后文中我会结合源码对这一过程进行分析)。Hashtable 没有这样的机制。

19.2 HashMap 的底层实现

实现原理:
HashMap 实际上是一个数组和链表的结合体, HashMap 基于 Hash 算法实现的;

(1) 当我们向 HashMap 中 Put 元素时, 利用 key 的 hashCode 重新计算出当前对象的 元素在数组中的下标

(2) 写入时, 如果出现 Hash 值相同的 key, 此时分类, 如果 key 相同, 则覆盖原始值; 如果 key 不同, value 则放入链表中

(3) 读取时, 直接找到 hash 值对应的下标, 在进一步判断 key 是否相同, 进而找到对 应值

  1. JDK1.8 之前

    JDK1.8 之前 HashMap 底层是 数组和链表 结合在一起使用也就是 链表散列。HashMap 通过 key 的 hashcode 经过扰动函数处理过后得到 hash 值,然后通过 (n - 1) & hash 判断当前元素存放的位置(这里的 n 指的是数组的长度),如果当前位置存在元素的话,就判断该元素与要存入的元素的 hash 值以及 key 是否相同,如果相同的话,直接覆盖,不相同就通过拉链法解决冲突。

    所谓扰动函数指的就是 HashMap 的 hash 方法。使用 hash 方法也就是扰动函数是为了防止一些实现比较差的 hashCode() 方法 换句话说使用扰动函数之后可以减少碰撞。

    所谓 “拉链法” 就是:将链表和数组相结合。也就是说创建一个链表数组,数组中每一格就是一个链表。若遇到哈希冲突,则将冲突的值加到链表中即可。
    在这里插入图片描述

  2. JDK1.8 之后
    相比于之前的版本, JDK1.8 之后在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为 8)(将链表转换成红黑树前会判断,如果当前数组的长度小于 64,那么会选择先进行数组扩容,而不是转换为红黑树)时,将链表转化为红黑树,以减少搜索时间。
    在这里插入图片描述

20. ArrayList 和 LinkedList 的区别 (重要)

(1) ArrayList 基于动态数据实现, LinkedList 基于链表实现, 两者都是线程不安全的
(2) ArrayList 基于数组, 查询快; linkedList 基于链表, 新增和删除更快
(3) LinkedList 不支持高效的随机访问

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

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

相关文章

视频滚动字幕一键批量轻松添加,解锁高效字幕编辑,提升视频质量与观众体验

视频已成为我们获取信息、娱乐休闲的重要渠道。一部成功的视频作品,除了画面精美、音质清晰外,字幕的添加也是至关重要的一环。字幕不仅能增强视频的观感,还能提升信息的传达效率,让观众在享受视觉盛宴的同时,更加深入…

vue项目使用百度地图

打开百度地图开放平台 百度地图开放平台 | 百度地图API SDK | 地图开发 在控制台新建应用 复制访问应用的ak 可修改地图样式 使用部分 <!-- 引入地图 --><div class"main-aside"><div id"b-map-container"></div></div> …

面试ssss

响应式布局 响应式布局是一种设计和开发网页的方法&#xff0c;使网页能够适应不同的设备和屏幕尺寸&#xff0c;提供更好的用户体验。它通过使用媒体查询&#xff08;Media Queries&#xff09;和弹性布局&#xff08;Flexbox&#xff09;等技术&#xff0c;根据设备的特性和…

一个docker配置mysql主从服务器

这也就是因为穷&#xff0c;不然谁用一个docker配置主从&#xff0c;哈哈 既然成功了就记录下。过程挺折磨人的。 首先要保证你的电脑安装好了docker 为了保证docker当中主从能正常连网&#xff0c;现在docker里面创建一个网络环境 docker network create --driver bridge mysq…

面试八股——RabbitMQ

消息丢失问题 消息确认机制 生产者与MQ之间的消息确认&#xff1a; 当MQ成功接收消息后&#xff0c;会返回给生产者一个确认消息。如果在规定时间内生产者未收到确认消息&#xff0c;则任务消息发送失败。 MQ与消费者之间的消息确认&#xff1a; 当MQ成功接收消息后&#…

DeepFaceLab小白教程:视频换脸过程

合适那些人阅读&#xff1f; 适合从未使用过DeepFaceLab的群体。 如果你想基于DeepFaceLab完成一次视频换脸的操作&#xff0c;可以看本篇。 下载方式 GitHub https://github.com/iperov/DeepFaceLab 我是用motrix下载。 网盘 https://pan.baidu.com/share/init?surlO4…

鸿蒙(HarmonyOS)性能优化实战-Swiper高性能开发

背景 在应用开发中&#xff0c;Swiper 组件常用于翻页场景&#xff0c;比如&#xff1a;桌面、图库等应用。Swiper 组件滑动切换页面时&#xff0c;基于按需加载原则通常会在下一个页面将要显示时才对该页面进行加载和布局绘制&#xff0c;这个过程包括&#xff1a; 如果该页面…

nest使用swagger文档

OpenAPI(Swagger)规范是一种用于描述 RESTful API 的强大定义格式。 Nest 提供了一个专用模块来使用它。 安装 npm安装 npm install --save nestjs/swagger swagger-ui-expressyarn 安装 yarn add nestjs/swagger swagger-ui-express引入 使用 SwaggerModule 类初始化 Swa…

【Hadoop】-Hive初体验[13]

Hive体验 预先确保已经完成部署Hive&#xff0c;并启动了Metastore服务 可以执行&#xff1a;bin/hive&#xff0c;进入到Hive Shell环境中&#xff0c;可以直接执行SQL语句。 创建表 create table test(id int,name string,gender string); 插入数据 INSERT INTO test val…

Golang基础2-Array、Slice、Map

Array 数组 var a [5]int b:[5]int{} c:[...]int{}这样格式定义var a[5]int 和var a[10]int是不同类型从0开始下标&#xff0c;到len(a)-1遍历方式&#xff1a; for i : 0; i < len(a); i { }for index, v : range a { } 注意越界问题&#xff0c;panic值类型&#xff0c;…

密码学 | Schnorr 协议:零知识身份证明和数字签名

&#x1f955;原文&#xff1a; Schnorr 协议&#xff1a;零知识身份证明和数字签名 &#x1f955;写在前面&#xff1a; 本文属搬运博客&#xff0c;自己留存学习。文中的小写字母表示标量&#xff0c;大写字母表示椭圆曲线中的点。 1 Schnorr 简介 Schnorr 由德国数学家和密…

windows系统下python开发工具安装

一. 简介 前一篇文章学习了安装 python解释器&#xff0c;文章如下&#xff1a; windows系统下python解释器安装-CSDN博客 本文来学习如何下载安装 python开发工具 PyCharm。 二. python开发工具 PyCharm下载安装 1. PyCharm官网 PyCharm开发工具 PyCharm为 python代码…

Llama网络结构介绍

LLaMA现在已经是开源社区里炙手可热的模型了&#xff0c;但是原文中仅仅介绍了其和标准Transformer的差别&#xff0c;并没有一个全局的模型介绍。因此打算写篇文章&#xff0c;争取让读者不参考任何其他资料把LLaMA的模型搞懂。 结构 如图所示为LLaMA的示意图&#xff0c;由…

域名被污染了只能换域名吗?

域名污染是指域名的解析结果受到恶意干扰或篡改&#xff0c;使得用户在访问相关网站时出现异常。很多域名遭遇过污染的情况&#xff0c;但是并不知道是域名污染&#xff0c;具体来说&#xff0c;域名污染可能表现为以下情况&#xff1a;用户无法通过输入正确的域名访问到目标网…

Windos环境下配置免费SSL证书详细步骤

获取免费证书 配置本机模拟域名 打开如下目录&#xff0c;hosts文件 C:\Windows\System32\drivers\etc 添加如下配置并保存 127.0.0.1 im.test.com下载安装 OpenSSL 下载链接 进入bin目录&#xff0c; 打开cmd窗口 执行如下命令&#xff0c;生成RSA私钥 ## 使用des3…

大型集团企业 怎么实现多区域文件交换?

很多大型集团企业&#xff0c;都会在全国各地&#xff0c;甚至海外&#xff0c;都设立分支机构&#xff0c;还有银行、邮政这类机构&#xff0c;都会在全国各地设立多个支行和网点&#xff0c;所以在日常经营过程中&#xff0c;都会存在多区域文件交换的场景。 大型集团企业在进…

JVM垃圾收集器--分区收集器

G1收集器 G1&#xff08;Garbage-First Garbage Collector&#xff09;在 JDK 1.7 时引入&#xff0c;在 JDK 9 时取代 CMS 成为了默认的垃圾收集器。G1 有五个属性&#xff1a;分代、增量、并行、标记整理、STW。 分代 G1收集器 将内部分为多个大小相等的区域&#xff0c;另…

Unity Shader 图形学【笔记一】

游戏图形学 源自&#xff1a;计算机图形学 涵盖&#xff1a;图形、动画的创建渲染展示 目标&#xff1a;性能优化、提高视觉质量&#xff0c;增强用户体验 技术&#xff1a;三维模型、纹理、光照、阴影、特效、动画、物理模拟、碰撞检测等 Unity Shader 是&#xff1a;un…

基于Vue+ElementPlus自定义带历史记录的搜索框组件

前言 基于Vue2.5ElementPlus实现的一个自定义带历史记录的搜索框组件 效果如图&#xff1a; 基本样式&#xff1a; 获取焦点后&#xff1a; 这里的历史记录默认最大存储10条&#xff0c;同时右侧的清空按钮可以清空所有历史记录。 同时搜索记录也支持点击搜索&#xff0c;按…

371D - Vessels

思路&#xff1a;用并查集维护&#xff0c;如果当前容器没有满&#xff0c;就指向自己&#xff0c;否则指向下一个容器。 这样就可以快速 find 到下一个没有满的容器&#xff0c;从而模拟询问 1。 代码&#xff1a; void solve(){int n;cin >> n;vector<int>p(n …