Java面试题总结(二):Java多线程

news2024/11/18 12:42:29

文章目录

    • 1.进程和线程的区别,进程间如何通信
    • 2. 什么是线程上下文切换
    • 3.什么是死锁
    • 4.死锁的必要条件
    • 5.Synchronized和lock的区别
    • 6.什么是AQS锁?
    • 7.为什么AQS使用的双向链表?
    • 8.有哪些常见的AQS锁
    • 9.sleep()和wait()的区别
    • 10.yield()和join()区别
    • 11.线程池七大参数
    • 12.Java内存模型
    • 13.保证并发安全的三大特性?
    • 14.volatile
    • 15.线程使用方式
    • 16.ThreadLocal原理
    • 17.什么是CAS锁
    • 18.Synchronized锁原理和优化
    • 19.如何根据 CPU 核心数设计线程池线程数量
    • 20.AtomicInteger的使用场景

1.进程和线程的区别,进程间如何通信

进程:系统运行的基本单位,进程在运行过程中都是相互独立,但是线程之间运行可以相互影响。

线程:独立运行的最小单位,一个进程包含多个线程且它们共享同一进程内的系统资源

进程间通过管道、 共享内存、信号量机制、消息队列通信

2. 什么是线程上下文切换

当一个线程被剥夺cpu使用权时,切换到另外一个线程执行

3.什么是死锁

死锁指多个线程在执行过程中,因争夺资源造成的一种相互等待的僵局

4.死锁的必要条件

互斥条件:同一资源同时只能由一个线程读取

不可抢占条件:不能强行剥夺线程占有的资源

请求和保持条件:请求其他资源的同时对自己手中的资源保持不放

循环等待条件:在相互等待资源的过程中,形成一个闭环

想要预防死锁,只需要破坏其中一个条件即可,比如使用定时锁、尽量让线程用相同的加锁顺序,还可以用银行家算法可以预防死锁

5.Synchronized和lock的区别

(1)synchronized是关键字,lock是一个类

(2) synchronized在发生异常时会自动释放锁,lock需要手动释放锁

(3)synchronized是可重入锁、非公平锁、不可中断锁,lock的ReentrantLock是可重入锁,可中断锁,可以是公平锁也可以是非公平锁

(4)synchronized是JVM层次通过监视器实现的,Lock是通过AQS实现的

6.什么是AQS锁?

AQS是一个抽象类,可以用来构造锁和同步类,如ReentrantLock,Semaphore,CountDownLatch,CyclicBarrier。

AQS的原理是,AQS内部有三个核心组件,一个是state代表加锁状态初始值为0,一个是获取到锁的线程,还有一个阻塞队列。当有线程想获取锁时,会以CAS的形式将state变为1,CAS成功后便将加锁线程设为自己。当其他线程来竞争锁时会判断state是不是0,不是0再判断加锁线程是不是自己,不是的话就把自己放入阻塞队列。这个阻塞队列是用双向链表实现的

可重入锁的原理就是每次加锁时判断一下加锁线程是不是自己,是的话state+1,释放锁的时候就将state-1。当state减到0的时候就去唤醒阻塞队列的第一个线程。

7.为什么AQS使用的双向链表?

因为有一些线程可能发生中断 ,而发生中断时候就需要在同步阻塞队列中删除掉,这个时候用双向链表方便删除掉中间的节点

8.有哪些常见的AQS锁

AQS分为独占锁和共享锁

ReentrantLock(独占锁):可重入,可中断,可以是公平锁也可以是非公平锁,非公平锁就是会通过两次CAS去抢占锁,公平锁会按队列顺序排队

Semaphore(信号量):设定一个信号量,当调用acquire()时判断是否还有信号,有就获取一个信号量,没有就阻塞等待其他线程释放信号量,当调用release()时释放一个信号量,唤醒阻塞线程。

应用场景:允许多个线程访问某个临界资源时,如上下车,买卖票

CountDownLatch(倒计数器):给计数器设置一个初始值,当调用CountDown()时计数器减一,当调用await() 时判断计数器是否归0,不为0就阻塞,直到计数器为0。

应用场景:启动一个服务时,主线程需要等待多个组件加载完毕,之后再继续执行

CyclicBarrier(循环栅栏):给计数器设置一个目标值,当调用await() 时会计数+1并判断计数器是否达到目标值,未达到就阻塞,直到计数器达到目标值

应用场景:多线程计算数据,最后合并计算结果的应用场景

9.sleep()和wait()的区别

(1)wait()是Object的方法,sleep()是Thread类的方法

(2)wait()会释放锁,sleep()不会释放锁

(3)wait()要在同步方法或者同步代码块中执行,sleep()没有限制

(4)wait()要调用notify()或notifyall()唤醒,sleep()自动唤醒

10.yield()和join()区别

yield()调用后线程进入就绪状态

A线程中调用B线程的join() ,则B执行完前A进入阻塞状态

11.线程池七大参数

核心线程数:线程池中的基本线程数量

最大线程数:当阻塞队列满了之后,逐一启动

最大线程的存活时间:当阻塞队列的任务执行完后,最大线长的回收时间

最大线程的存活时间单位

阻塞队列:当核心线程满后,后面来的任务都进入阻塞队列

线程工厂:用于生产线程

任务拒绝策略:阻塞队列满后,拒绝任务,有四种策略(1)抛异常(2)丢弃任务不抛异常(3)打回任务(4)尝试与最老的线程竞争

12.Java内存模型

JMM(Java内存模型 )屏蔽了各种硬件和操作系统的内存访问差异,实现让Java程序在各平台下都能达到一致的内存访问效果,它定义了JVM如何将程序中的变量在主存中读取

具体定义为:所有变量都存在主存中,主存是线程共享区域;每个线程都有自己独有的工作内存,线程想要操作变量必须从主从中copy变量到自己的工作区,每个线程的工作内存是相互隔离的

由于主存与工作内存之间有读写延迟,且读写不是原子性操作,所以会有线程安全问题

13.保证并发安全的三大特性?

原子性:一次或多次操作在执行期间不被其他线程影响

可见性:当一个线程在工作内存修改了变量,其他线程能立刻知道

有序性:JVM对指令的优化会让指令执行顺序改变,有序性是禁止指令重排

14.volatile

保证变量的可见性和有序性,不保证原子性。使用了 volatile 修饰变量后,在变量修改后会立即同步到主存中,每次用这个变量前会从主存刷新。

单例模式双重校验锁变量为什么使用 volatile 修饰? 禁止 JVM 指令重排序,new Object()分为三个步骤:为实例对象分配内存,用构造器初始化成员变量,将实例对象引用指向分配的内存;实例对象在分配内存后实才不为null。如果分配内存后还未初始化就先将实例对象指向了内存,那么此时最外层的if会判断实例对象已经不等于null就直接将实例对象返回。而此时初始化还没有完成。

15.线程使用方式

(1)继承 Tread 类

(2)实现 Runnable 接口

(3)实现 Callable 接口:带有返回值

(4)线程池创建线程

16.ThreadLocal原理

原理是为每个线程创建变量副本,不同线程之间不可见,保证线程安全。每个线程内部都维护了一个Map,key为threadLocal实例,value为要保存的副本。
但是使用ThreadLocal会存在内存泄露问题,因为key为弱引用,而value为强引用,每次gc时key都会回收,而value不会被回收。所以为了解决内存泄漏问题,可以在每次使用完后删除value或者使用static修饰ThreadLocal,可以随时获取value

17.什么是CAS锁

CAS锁可以保证原子性,思想是更新内存时会判断内存值是否被别人修改过,如果没有就直接更新。如果被修改,就重新获取值,直到更新完成为止。这样的缺点是

(1)只能支持一个变量的原子操作,不能保证整个代码块的原子操作

(2)CAS频繁失败导致CPU开销大

(3)ABS问题:线程1和线程2同时去修改一个变量,将值从A改为B,但线程1突然阻塞,此时线程2将A改为B,然后线程3又将B改成A,此时线程1将A又改为B,这个过程线程2是不知道的,这就是ABA问题,可以通过版本号或时间戳解决

18.Synchronized锁原理和优化

Synchronize是通过对象头的markwordk来表明监视器的,监视器本质是依赖操作系统的互斥锁实现的。操作系统实现线程切换要从用户态切换为核心态,成本很高,此时这种锁叫重量级锁,在JDK1.6以后引入了偏向锁、轻量级锁、重量级锁

偏向锁:当一段代码没有别的线程访问,此时线程去访问会直接获取偏向锁

轻量级锁:当锁是偏向锁时,有另外一个线程来访问,会升级为轻量级锁。线程会通过CAS方式获取锁,不会阻塞,提高性能,

重量级锁:轻量级锁自旋一段时间后线程还没有获取到锁,会升级为重量级锁,重量级锁时,来竞争锁的所有线程都会阻塞,性能降低

注意,锁只能升级不能降级

19.如何根据 CPU 核心数设计线程池线程数量

IO 密集型:线程中十分消耗Io的线程数*2
CPU密集型: cpu线程数量

20.AtomicInteger的使用场景

AtomicInteger是一个提供原子操作的Integer类,使用CAS+volatile实来现线程安全的数值操作。

因为volatile禁止了jvm的排序优化,所以它不适合在并发量小的时候使用,只适合在一些高并发程序中使用

在这里插入图片描述

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

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

相关文章

【C++进阶(八)】C++继承深度剖析

💓博主CSDN主页:杭电码农-NEO💓   ⏩专栏分类:C从入门到精通⏪   🚚代码仓库:NEO的学习日记🚚   🌹关注我🫵带你学习C   🔝🔝 继承 1. 前言2. 继承的基本概念3. 继承关系和访…

全球二氧化碳排放数据1deg产品(ODIAC)数据

简介 全球二氧化碳排放数据1deg产品(ODIAC)是一个空间分辨率为1deg*1deg的全球化石燃料燃烧产生的二氧化碳空间分布产品。它率先将基于空间的夜间灯光数据与单个发电厂的排放/位置相结合来估计化石燃料二氧化碳的排放。该产品被国际研究界广泛用于各种研究应用(例如…

微信小程序的OA会议之首页搭建

目录 一.小程序的布局 1.1. flex是什么 1.2. flex布局 1.3.总体布局 二.轮播图 2.1. 组件 2.2. 数据请求 2.3. 页面 三.首页 2.1. 视图 2.2.数据 2.3. 样式 好啦今天就到这里了,希望能帮到你哦!!! 一.小程序的布局 …

Linux入门攻坚——4、shell编程初步、grep及正则表达式

bash的基础特性(续): 1、提供了编程环境: 编程风格:过程式:以指令为中心,数据服务于执行;对象式:以数据为中心,指令服务于数据 shell编程,编译执…

面向JS程序员的TypeScript

定义类型 你可以在 JavaScript 中使用多种设计模式。 但是,某些设计模式使得自动推断类型变得困难(例如,使用动态编程的模式)。 为了涵盖这些情况,TypeScript 支持 JavaScript 语言的扩展,它为你提供了告诉…

YOLOv5改进实战 | 更换主干网络Backbone之轻量化网络EMO,结合 CNN 和 Transformer 的现代倒残差移动模块设计

前言 传统的YOLOv5系列中,Backbone采用的是较为复杂的C3网络结构,这使得模型计算量大幅度的增加,检测速度较慢,应用受限,在某些真实的应用场景如移动或者嵌入式设备,如此大而复杂的模型时难以被应用的。为了解决这个问题,本章节通过采用EMO轻量化主干网络作为Backbone的…

Python+unittest+requests接口自动化测试框架搭建 完整的框架搭建过程

首先配置好开发环境,下载安装Python并下载安装pycharm,在pycharm中创建项目功能目录。如果不会的可以百度Google一下,该内容网上的讲解还是比较多比较全的! 大家可以先简单了解下该项目的目录结构介绍,后面会针对每个文…

黑豹程序员-架构师学习路线图-百科:MVC的演变终点SpringMVC

MVC发展史 在我们开发小型项目时,我们代码是混杂在一起的,术语称为紧耦合。 如最终写ASP、PHP。里面既包括服务器端代码,数据库操作的代码,又包括前端页面代码、HTML展现的代码、CSS美化的代码、JS交互的代码。可以看到早期编程就…

mysql反斜杠多次转义简述

概述 通常在业务中会用正则/like去匹配一些数据.如果数据中有反斜杠,或者是用的正则语句。 那么在写sql的时候就需要转义下反斜杠,转义的时候有几个隐藏问题需要注意。 使用like做where条件 如下使用like要查询这两条数据的时候,需要用8个…

Android音视频开发之基础知识

一、视频文件 1、视频格式 常见格式:mp4、mkv、flv 封装的数据:音频码流、视频码流 常用工具: [FFmpeg下载]:https://ffmpeg.org/download.html 下载、安装并配置环境变量 ffmpeg.exe 视频编解码 ffplay.exe 播放器库 ffprobe.exe 音视频分…

【三:Spring整合Mybatis】

目录 Spring整合Mybatis(基于xml文件)1 、项目的大体框架前期准备1.2 、使用Navicat在数据库中创建一张表account1.3、 在pom.xml文件中加入maven(依赖的配置)1.4、配置相应的数据库连接,以及扫描相应的dao层 编写实体…

Unity中Shader实现UI流光效果

文章目录 前言一、实现思路1:1、采集两张贴图,一张是主纹理,一张是扫光纹理2、在 v2f 定义一个二维变量 “uv2” 来存放 uv 偏移后的值3、在顶点着色器中,仿照之前的 uv 流动效果,与 _Time相乘后存放于 uv2 中4、最后,…

微信小程序中封装请求,使用Async await方法,将异步请求变为同步请求方法

介绍 微信小程序中,很多 API都是异步的,无法同步处理。可以使用高级封装,通过async await方法来同步处理。 方法 在小程序右上角的 详情 里选择 本地设置 , 勾选 ES6转ES5,如下所示: 由于 Async Await 是 ES7语法&a…

Boost.Beast和C++编写程序

以下是一个使用Boost.Beast和C编写的爬虫程序&#xff0c;用于爬取。此程序使用了proxy的代码。 #include <iostream> #include <string> #include <boost/asio.hpp> #include <boost/beast.hpp> ​ std::string get_audio_url(const std::string&…

第十七章 Java连接数据库

1.打卡“命令提示符”&#xff0c;用管理员身份运行 2.登录MySQL 3.创建库和表 4.使用Java命令查询数据库操作 5.右击——点击“Build Path”——选择第四个——找到包的位置——导入成功 一、创建java项目 二、连接数据库 1.注册驱动 2.获取链接 3.获取statment对象 4.…

docker命令实例(举例子学习)

docker命令实例 实例1 docker build -t linksoul/chinese-llama2-chat .实例2 docker run --gpus all --ipchost --ulimit memlock-1 --ulimit stack67108864 --rm -it -v pwd/LinkSoul:/app/LinkSoul -p 7860:7860 linksoul/chinese-llama2-chat实例3 docker run -it -p 78…

QT串口接收数据并进行波形显示(含源码)

**使用QT在串口调试助手基础上实现波形显示&#xff08;含源码&#xff09; 评论比较多留言需要源码的&#xff0c;逐个发邮箱比较麻烦也不能及时回复&#xff0c;现将源码上传至链接&#xff08;无需积分下载&#xff09;https://download.csdn.net/download/m0_51294753/877…

Jupyter Notebook 设置黑色背景主题

Jupyter Notebook 设置黑色背景主题 # 包安装 pip install jupyterthemes -i https://mirrors.aliyun.com/pypi/simple pip install --upgrade jupyterthemes # 查看可用主题 jt -l # monokai暗背景&#xff0c;-f(字体) -fs(字体大小) -cellw(占屏比或宽度) -ofs(输出段的字…

自己DIY一个模拟多按钮电路

普通按键电路原理&#xff1a; 一般使用的按键原理图如下图所示&#xff0c;由按键、上拉电阻和消抖滤波电容组成。按键断开时KeyIin1处电压被上拉到5V&#xff0c;当按键闭合时把KeyIin1电压拉到0V&#xff0c;与按键并联的电容起到滤除按键按下与弹起时的高频信号。 如果在电…

让uniGUI支持https

今天在专家的帮助下&#xff0c;成功的让uniGUI支持https了。 首先&#xff0c;去申请个**的证书。我同事去阿里申请的&#xff0c;申请回是一个zip文件&#xff0c;里面有两个文件&#xff0c;一个扩展是per&#xff0c;一个key 然后&#xff0c;把这两个证书文件放到uniGUI…