面试八股文(3)

文章目录

      • 1.HashSet如何检查重复
      • 2.comparable和Comparator区别
      • 3.ConcurrentHashMap和Hashtable区别
      • 4.线程和进程
      • 5.并发与并行的区别
      • 6.为什么使用多线程
      • 7.使用多线程可能带来问题
      • 8.线程的生命周期和状态
      • 9.什么是上下文切换
      • 10.线程死锁
      • 11.产生死锁四个条件
      • 12.如何避免死锁

1.HashSet如何检查重复

当你把对象加入HashSet时,HashSet会先计算对象的hasdcode值来判断对象加入的位置,同时也会与其他加入的对象的hashcode值作比较,如果没有相符的hashcode,HashSet会假设对象没有重复出现。但是如果发现有相同的hashcode值的对象,这时会调用equals()方法来检查hashcode相等的对象是否真的相同。如果两者相同,HashSet就不会让加入操作成功。

2.comparable和Comparator区别

  • comparable接口实际上是出自java.lang包,它有一个compareTo(Object obj)方法用来排序。
  • comparator接口实际上是出自java.util包,它有一个compare(Object obj1,Object obj2)方法用来排序。

3.ConcurrentHashMap和Hashtable区别

ConcurrentHashMap和Hashtable的区别主要体现在实现线程安全的方式上不同。

  • 底层数据结构:JDK1.7的ConcurrentHashMap底层采用分段数组+链表实现,JDK1.8采用的数据结构跟HashMap1.8的结构一样,数组+链表/红黑二叉树。Hashtable的JDK1.8之前的HashMap的底层数据结构类似都是采用数组+链表的形式,数组是HashMap的主体,链表则是主要为了解决哈希冲突而存在的。
  • 实现线程安全的方式:在JDK1.7的时候,ConcurrentHashMap(分段锁)对整个桶数组进行了分割分段(Segment),每一把锁只锁容器其中的一部分数据,多线程访问容器里不同的数据段的数据,就不会存在锁竞争,提高并发访问率。到了JDK1.8的时候已经摒弃了Segment的概念,而是直接用Node数组+链表+红黑树的数据结构来实现,并发控制使用synchronized和CAS来操作。(JDK1.6以后对synchronized锁做了很多优化)整个看起来像是优化过且线程安全的HashMap,虽然在JDK1.8中还能看到Segment的数据结构,但是已经简化了属性,只是为了兼容低版本;Hashtable使用synchronized来保证线程安全,效率非常低下。当一个线程访问同步方法时,其他线程也访问同步方法,可能会进入阻塞或轮询状态,如使用put添加元素,另一个线程不能使用put添加元素,也不能使用get,竞争会越来越激烈效率越低。

4.线程和进程

进程
进程是程序的一次执行过程,是系统运行程序的基本单位,因此进程是动态的。系统运行一个程序即是一个进程从创建、运行到消亡的过程。
在Java中,当我们启动main函数时其实就是启动了一个JVM的进程,而main函数所在的线程就是这个进程中的一个线程,也称主线程。
线程
线程与进程类似,但线程是一个比进程更小的执行单位。一个进程在其执行过程中可以产生多个线程。与进程不同的是同类的多个线程共享进程的堆和方法区资源,但每个线程有自己的程序计数器、虚拟机栈和本地方法栈,所以系统在产生一个线程,或是在各个线程之间切换工作时,负担要比进程小得多,因此,线程被称为轻量级进程。
区别
线程是进程划分成的更小的运行单位。线程和进程最大的不同在于基本上各进程是独立的,而各线程则不一定,因为同一进程中的线程极有可能会相互影响。线程执行开销小,但是不利于资源的管理和保护,而进程相反。

5.并发与并行的区别

  • 并发:同一时间段,多个任务都在执行(单位时间内不一定同时执行)。
  • 并行:单位时间内,多个任务同时执行。

6.为什么使用多线程

先从总体上来说:

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

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

并发编程目的就是为了能够提高程序的执行效率提高程序运行速度,但是并发编程并不总是能提高程序运行速度的,而且并发编程可能会遇到很多问题,比如:内存泄漏、上下文切换、死锁还有受限于硬件和软件的资源闲置问题。

8.线程的生命周期和状态

状态名称说明
NEW初始状态,线程被构建,但是还没有调用start()方法
RUNNABLE运行状态,Java线程将操作系统中的就绪和运行两种状态笼统地称为运行中
BLOCKED阻塞状态,表示线程阻塞于锁
WAITING等待状态,表示线程进入等待状态,进入该状态表示当前线程需要等待其他线程做出一些特定动作(通知或中断)
TIMED_WAITING超时等待状态,该状态不同于WAITING,它是可以在指定的时间自行返回的
TERMINATED终止状态,表示当前线程已经运行完毕

线程创建之后处于NEW(新建)状态,调用start()方法后开始运行,线程这时候处于READY(可运行)状态。可运行状态的线程获得CPU时间片(timeslice)后就处于RUNNING(运行)状态。当线程执行wait()方法之后,线程进入WAITING(等待)状态。进入等待状态的线程需要依靠其他线程的通知才能返回到运行状态,而TIME_WAITING(超时等待)状态相当于在等待状态的基础上增加了超时限制,比如通过sleep(long millis)方法或wait(long millis)方法可以将Java线程置于TIMED WAITING状态。当超时时间到达后Java线程将会返回到RUNNABLE状态。当线程调用同步方法时,在没有获取到锁的情况下,线程将会进入**BLOCKED(阻塞)状态。线程在执行Runnable的run()方法之后将会进入到TERMINATED(终止)**状态。

9.什么是上下文切换

多线程编程中一般线程的个数都大于CPU核心的个数,而一个CPU核心在任意时刻只能被一个线程使用,为了让这些线程都能得到有效执行,CPU采取的策略是为每个线程分配时间片并轮转的形式。当一个线程的时间片用完的时候就会重新处于就绪状态让给其他线程使用,这个过程就属于一次上下文切换。

概括来说:当前任务在执行完CPU时间片切换到另一个任务之前会保存自己的状态,以便下次再切换回这个任务时,可以再加载这个人物的状态。任务从保存到再加载的过程就是一次上下文切换。

10.线程死锁

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

11.产生死锁四个条件

  1. 互斥条件:该资源任意一个时刻只由一个线程占用。
  2. 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
  3. 不剥夺条件:线程已获得的资源在未使用完之前不能被其他线程强行剥夺,只有自己使用完毕后才释放资源。
  4. 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

12.如何避免死锁

为了避免死锁,只要破坏产生死锁的四个条件中的一个:

  1. 破坏互斥条件:这个条件我们没有办法破坏,因为我们用锁本来就是想让他们互斥(临界资源需要互斥访问)。
  2. 破坏请求与保持条件:一次性申请所有的资源。
  3. 破坏不剥夺条件:占用部分资源的线程进一步申请其他资源时,如果申请不到,可以主动释放它占有的资源。
  4. 破坏循环等待条件:靠按序申请资源来预防。按某一顺序申请资源,释放资源则反序释放。

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

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

相关文章

游戏如何选择服务器

一个网络游戏要想长期运行下去,关键是用户体验,在初期阶段的游戏服务器租用环节就显得尤为重要。那么问题来了,游戏公司如何才能够在众多的服务器商中租用找到高性能、高性价比的游戏服务器租用呢?租用游戏服务器时需要考虑的因素…

幻兽帕鲁游戏中走路卡顿并且会出现回弹是什么原因?

可能原因是最近的 1.4.0 更新后,代码中有一个启动参数的加入,导致 CPU 占用极高。 可以远程连接你的服务器 然后执行下面的代码,删除代码中的那个启动参数。 # 删除可能导致人物回弹的游戏服务器启动参数 sudo -u ecs-assist-user sed -i s…

英码科技携手昇腾共建算力底座:推出EA500I超强AI处理能力边缘计算盒子!

在数字经济浪潮中,算力已成为不可或缺的驱动力,为各行各业的数字化转型提供了强大的推动力。面对多元化和供需不平衡的挑战,需要实现从理论架构到软硬件实现的质的飞跃,以满足持续增长的算力需求,华为昇腾在这一方面展…

【SpringBoot】RBAC权限控制

📝个页人主:五敷有你 🔥系列专栏:SpringBoot⛺️稳重求进,晒太阳 权限系统与RBAC模型 权限 为了解决用户和资源的操作关系, 让指定的用户,只能操作指定的资源。 权限功能 菜单权限&a…

前端学习笔记 | 响应式网页+Boostrap

一、响应式网页 一套代码适应多端 1、媒体查询media(条件){css} max-width 小于等于max-width生效min-width 【案例】左侧隐藏 因为CSS的层叠性,书写顺序:max-width从大到小;min-width从小到大。 【媒体查询完整写法】 在html中link用于不同…

【pwn】pwnable_start --只有read和write函数的getshell

首先查一下程序的保护情况 保护全关!!! 然后看ida逻辑 ida的结果很简洁,只有一段汇编代码,我们再来看看nc情况 现在我们来分析一下汇编代码 mov ecx, esp ; addr .text:08048089 B2 14 …

RHCE 综合项目-博客

目录 业务需求 一、准备工作 1、配置静态IP 2、修改主机名及hosts映射 3、开启防火墙 4、时间同步 5、配置免密ssh登录 二、环境搭建 1、Server-web端安装LAMP环境软件 2、Server-NFS-DNS端上传博客软件 3、Server-NFS-DNS端设置NFS共享 三、Server-web设置 1、挂…

【DDD】学习笔记-数据分析模型

在 Eric Evans 提出领域驱动设计之前,对企业系统的分析设计多数采用数据模型驱动设计。如前所述,这种数据模型驱动设计就是站在数据的建模视角,逐步开展分析、设计与实现的建模过程。通过对数据的正确建模,设计人员就可以根据模型…

ADAS感知摄像头的分辨率与帧率选择分析

说明:可以作为对智能驾驶爱好者对摄像头参数理解或者从业工程人员对设计硬件选型参考 前言 在当前智能驾驶中,基于摄像头的 ADAS 因其应用、更高的可靠性和对新要求的适应性而被广泛采用。 ADAS 摄像头通常部署在汽车的前部、侧面和后部,提…

【代码随想录-哈希表】有效的字母异位词

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学习,不断总结,共同进步,活到老学到老导航 檀越剑指大厂系列:全面总结 jav…

爬什么值得买的榜单——爬虫练习题目一(问)

爬虫题目你敢试试吗? 引言具体原因网站思路总体 我让AI给个框架1. **项目初始化与依赖安装**2. **定义数据模型**3. **网络请求模块**4. **页面解析模块**5. **数据存储模块**6. **主程序流程** 结尾 引言 最近在做什么呢 建立一套完整的信息输入输出系统 在我上一…

Flutter canvas 画一条会动的波浪线 进度条

之前用 Flutter Canvas 画过一个三角三角形,html 的 Canvas 也画过一次类似的, 今天用 Flutter Canvas 试了下 感觉差不多: html 版本 大致效果如下: 思路和 html 实现的类似: 也就是找出点的位置,使用二阶…