Java知识复习(四)多线程、并发编程

news2024/11/25 16:05:31

1、进程、线程和程序

  1. 进程:进程是程序的一次执行过程,是系统运行程序的基本单位,因此进程是动态的;在 Java 中,当我们启动 main 函数时其实就是启动了一个 JVM 的进程,而 main 函数所在的线程就是这个进程中的一个线程,也称主线程
  2. 线程:线程与进程相似,但线程是一个比进程更小的执行单位;与进程不同的是同类的多个线程共享进程的堆和方法区资源,但每个线程有自己的程序计数器、虚拟机栈和本地方法栈;简单来说就是进程有资源,而线程几乎没有,它只是一个调度的单位,资源使用的是进程的
  3. 程序:指含有指令和数据的文件,被存储在磁盘或其他的数据存储设备中,也就是说程序是静态的代码,一个可执行的文件

2、虚拟机栈和本地方法栈为什么是私有的?

  1. 虚拟机栈:每个 Java 方法在执行的同时会创建一个栈帧用于存储局部变量表、操作数栈、常量池引用等信息。从方法调用直至执行完成的过程,就对应着一个栈帧在 Java 虚拟机栈中入栈和出栈的过程
  2. 本地方法栈:和虚拟机栈的作用相似,不同的是为使用到的Native方法服务(Native方法指用其他语言,比如c实现的方法)
  3. 所以,为了保证线程中的局部变量不被别的线程访问到,虚拟机栈和本地方法栈是线程私有的

3、线程的生命周期

  1. 初始状态:线程被创建出来,但没有被调用
  2. 运行状态:线程被调用了start()等待运行的状态(这里包括了就绪和运行中两种状态)
  3. 阻塞状态:需要等待锁被释放
  4. 等待状态:表示该线程需要等待其他线程做出一些特定动作(通知或中断)
  5. 超时等待状态:可以在指定的时间后自行返回
  6. 终止状态:表示该线程已经运行完毕
    在这里插入图片描述
    注意: 这里没有区分就绪和运行两种状态是因为现代操作系统的时间片太小了,以至于区分二者没有太多意义。

4、上下文切换

  1. 上下文:线程在执行过程中会有自己的运行条件和状态,比如上文所说到过的程序计数器,栈信息等
  2. 上下文切换:在线程切换时保存当前线程的上下文,留待线程下次占用 CPU 的时候恢复现场,并加载下一个将要占用 CPU 的线程上下文

5、线程死锁

1、线程死锁:多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放

2、四个必要条件:简单来说就是:“你不松手我也不松手”

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

6、预防死锁和死锁避免

1、预防死锁:破坏四个必要条件之一

2、避免死锁:银行家算法

7、sleep()方法和wait()方法

  • 共同点:都可以暂停线程的执行
  • 不同点:sleep方法没有释放锁,而wait方法释放了锁;sleep方法执行后,线程会自动苏醒,而wait方法需要notify方法唤醒;sleep是Thread类的静态本地方法,而wait是Object类的本地方法

8、可以直接调用Thread类的run方法吗

回答: 调用 start() 方法方可启动线程并使线程进入就绪状态,当分配到时间片后就可以开始自动执行run()方法,但如果直接执行 run() 方法的话不会以多线程的方式执行,而是被当做main线程下的一个普通方法去执行

9、volatile关键字

  • volatile关键字可以保证变量的可见性,指示JVM这个变量共享且不稳定,每次使用它都得到主存中进行读取
  • 还有一个作用就是防止JVM的指令重排序
  • volatile关键字不能保证对变量的操作是原子性的,但synchronized可以

10、乐观锁和悲观锁

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

  • 通常用于读比较多的情况
  • 版本号机制:每次修改数据都会更新版本号,每次提交更新数据时会比较版本号,只有版本号一致时才更新
  • CAS算法:全称Compare And Swap(比较与交换),思想就是用一个预期值和要更新的变量值进行比较,两值相等才会进行更新;CAS是一条原子操作,因此当多个线程同时使用 CAS 操作一个变量时,只有一个会胜出,并成功更新,其余均会失败,但失败的线程并不会被挂起,仅是被告知失败,并且允许再次尝试,当然也允许失败的线程放弃操作

2、悲观锁:总是假设最坏的情况,认为共享资源每次被访问的时候就会出现问题(比如共享数据被修改),所以每次在获取资源操作的时候都会上锁,这样其他线程想拿到这个资源就会阻塞直到锁被上一个持有者释放(例如synchronized的独占锁);通常用于写比较多的情况

11、乐观锁存在的问题

1、ABA问题: 如果一个变量 V 初次读取的时候是 A 值,并且在准备赋值的时候检查到它仍然是 A 值,那我们就能说明它的值没有被其他线程修改过了吗?很明显是不能的,因为在这段时间它的值可能被改为其他值,然后又改回 A,那 CAS 操作就会误认为它从来没有被修改过。

解决思路: ABA 问题的解决思路是在变量前面追加上版本号或者时间戳

2、循环时间长开销大: CAS 经常会用到自旋操作来进行重试,也就是不成功就一直循环执行直到成功。如果长时间不成功,会给 CPU 带来非常大的执行开销

解决思路: 使用处理器提供的pause指令延迟流水线执行指令

3、只能保证一个共享变量的原子操作: CAS 只对单个共享变量有效,当操作涉及跨多个共享变量时 CAS 无效

解决思路: 我们可以使用锁或者利用AtomicReference类把多个共享变量合并成一个共享变量来进行CAS操作

12、synchronized关键字

1、synchronized(同步): 主要解决的是多个线程之间访问资源的同步性,可以保证被它修饰的方法或者代码块在任意时刻只能有一个线程执行

2、使用方式:

  • 修饰实例方法:锁当前对象实例加锁,进入同步代码前要获得当前对象实例的锁
  • 修饰静态方法:给当前类加锁,会作用于类的所有对象实例 ,进入同步代码前要获得当前 class 的锁
  • 修饰代码块:对括号里指定的对象/类加锁synchronized(object/类.class):表示进入同步代码库前要获得给定对象或者类的锁
  • 注意:构造方法不能用synchronized关键字修饰,因为构造方法本身就属于线程安全的

13、synchronized和volatile有什么区别

  • synchronized 关键字和 volatile 关键字是两个互补的存在,而不是对立的存在!
  • volatile 关键字是线程同步的轻量级实现,所以 volatile性能肯定比synchronized关键字要好。但是 volatile 关键字只能用于变量而 synchronized 关键字可以修饰方法以及代码块
  • volatile 关键字能保证数据的可见性,但不能保证数据的原子性。synchronized 关键字两者都能保证
  • volatile关键字主要用于解决变量在多个线程之间的可见性,而 synchronized 关键字解决的是多个线程之间访问资源的同步性

14、公平锁和非公平锁

  • 公平锁 : 锁被释放之后,先申请的线程先得到锁。性能较差一些,因为公平锁为了保证时间上的绝对顺序,上下文切换更频繁
  • 非公平锁 :锁被释放之后,后申请的线程可能会先获取到锁,是随机或者按照其他优先级排序的。性能更好,但可能会导致某些线程永远无法获取到锁

15、可中断锁和不可中断锁

  • 可中断锁 :获取锁的过程中可以被中断,不需要一直等到获取锁之后 才能进行其他逻辑处理。ReentrantLock 就属于是可中断锁
  • 不可中断锁 :一旦线程申请了锁,就只能等到拿到锁以后才能进行其他的逻辑处理。 synchronized 就属于是不可中断锁

16、ThreadLocal

1、ThreadLocal类: 主要解决的就是让每个线程绑定自己的值

  • 可以将ThreadLocal类形象的比喻成存放数据的盒子,盒子中可以存储每个线程的私有数据
  • 如果你创建了一个ThreadLocal变量,那么访问这个变量的每个线程都会有这个变量的本地副本,这也是ThreadLocal变量名的由来
  • 他们可以使用 get() 和 set() 方法来获取默认值或将其值更改为当前线程所存的副本的值,从而避免了线程安全问题

2、ThreadLocalMap: 最终的变量是放在了当前线程的 ThreadLocalMap 中,并不是存在 ThreadLocal 上,ThreadLocal 可以理解为只是ThreadLocalMap的封装,传递了变量值

  • 每个Thread中都具备一个ThreadLocalMap,而ThreadLocalMap可以存储以ThreadLocal为 key ,Object 对象为 value 的键值对

3、内存泄漏:

  • ThreadLocalMap 中使用的 key 为 ThreadLocal 的弱引用,而 value 是强引用
  • 如果 ThreadLocal 没有被外部强引用的情况下,在垃圾回收的时候,key 会被清理掉,而 value 不会被清理掉
  • 这样一来,ThreadLocalMap 中就会出现 key 为 null 的 Entry。假如我们不做任何措施的话,value 永远无法被 GC 回收,这个时候就可能会产生内存泄露
  • ThreadLocalMap 实现中已经考虑了这种情况,在调用 set()、get()、remove() 方法的时候,会清理掉 key 为 null 的记录。使用完 ThreadLocal方法后 最好手动调用remove()方法

17、线程池

1、线程池: 顾名思义,线程池就是管理一系列线程的资源池。当有任务要处理时,直接从线程池中获取线程来处理,处理完之后线程并不会立即被销毁,而是等待下一个任务

2、创建方法:

  • 方式一:通过ThreadPoolExecutor构造函数来创建(推荐)
  • 方式二:通过 Executor 框架的工具类 Executors 来创建

18、Future类

1、Future类: 是异步思想的典型运用,主要用在一些需要执行耗时任务的场景,避免程序一直原地等待耗时任务执行完成,执行效率太低

2、简单理解就是: 我有一个任务,提交给了 Future 来处理。任务执行期间我自己可以去做任何想做的事情。并且,在这期间我还可以取消任务以及获取任务的执行状态。一段时间之后,我就可以 Future 那里直接取出任务执行结果

19、AQS

1、AQS: 全称为 AbstractQueuedSynchronizer ,翻译过来的意思就是抽象队列同步器,为构建锁和同步器提供了一些通用功能的实现

2、AQS的核心原理: 如果被请求的共享资源空闲,则将当前请求资源的线程设置为有效的工作线程,并且将共享资源设置为锁定状态;如果被请求的共享资源被占用,那么就需要一套线程阻塞等待以及被唤醒时锁分配的机制,这个机制 AQS 是用 CLH 队列锁 实现的,即将暂时获取不到锁的线程加入到队列中

  • CLH 队列是一个虚拟的双向队列(虚拟的双向队列即不存在队列实例,仅存在结点之间的关联关系)
  • 使用 int 成员变量 state 表示同步状态,通过内置的 线程等待队列 来完成获取资源线程的排队工作

20、Semaphore

1、synchronized 和 ReentrantLock 都是一次只允许一个线程访问某个资源,而Semaphore(信号量)可以用来控制同时访问特定资源的线程数量

2、Semaphore的原理: 是共享锁的一种实现,它默认构造 AQS 的 state 值为 permits,你可以将 permits 的值理解为许可证的数量,只有拿到许可证的线程才能执行

21、CountDownLatch和CyclicBarrier关键字

1、CountDownLatch 的作用就是 允许 count 个线程阻塞在一个地方,直至所有线程的任务都执行完毕

2、CyclicBarrier 的字面意思是可循环使用(Cyclic)的屏障(Barrier)。它要做的事情是:让一组线程到达一个屏障(也可以叫同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续干活

3、CyclicBarrier 和 CountDownLatch 非常类似,它也可以实现线程间的技术等待,但是它的功能比 CountDownLatch 更加复杂和强大

22、线程的常用方法

  1. 线程睡眠:sleep方法,休眠一会儿,睡到自然醒
  2. 线程等待:wait方法,停下别动,等待通知
  3. 线程让步:yield方法,让出CPU时间片给优先级高的线程
  4. 线程中断:interrupt方法,修改内部维护的中断标识符,但不会直接打断一个正在运行的线程
  5. 线程加入:join方法,等待子线程执行结束
  6. 线程唤醒:notify方法,动起来,开始干活
  7. 后台守护线程:setDaemon方法,提供公共服务,默默干些杂活,比如垃圾回收线程

参考

  1. Java并发常见面试题总结
  2. 《Offer来了:Java面试核心知识点》

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

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

相关文章

JAVA开发(JAVA垃圾回收的几种常见算法)

JAVA GC 是JAVA虚拟机中的一个系统或者说是一个服务,专门是用于内存回收,交还给虚拟机的功能。 JAVA语言相对其他语言除了跨平台性,还有一个最重要的功能是JAVA语言封装了对内存的自动回收。俗称垃圾回收器。所以有时候我们不得不承认&#…

超实用的公众号用户运营方案分享,纯干货

公众运营是以用户为主的: 但是你知道什么是用户运营吗?你的公众号有没有维护好目标用户群体呢?你知道该怎么分析你的公众号用户群体吗?你知道分析完之后具体应该怎么做用户运营吗? 接下来伯乐网络传媒就来给大家分享…

第八届蓝桥杯省赛——7EXCLE地址

题目:Excel单元格的地址表示很有趣,它使用字母来表示列号。比如,A表示第1列,B表示第2列,Z表示第26列,AA表示第27列,AB表示第28列,BA表示第53列,....当然Excel的最大列号是…

【Spring Cloud Alibaba】(五)Dubbo启动报错?一直重连报错?你值得学习的是排查问题的方法

系列目录 【Spring Cloud Alibaba】(一)微服务介绍 及 Nacos注册中心实战 【Spring Cloud Alibaba】(二)微服务调用组件Feign原理实战 【Spring Cloud Alibaba】(三)OpenFeign扩展点实战 源码详解 【Spri…

2.1操作系统-进程管理:进程基本概念、进程与程序、进程与线程、进程的状态、进程三态模型、进程五态模型

2.1操作系统-进程管理:进程基本概念、进程与程序、进程与线程、进程的状态、进程三态模型、进程五态模型进程基本概念进程与程序进程与线程进程的状态进程三态模型进程五态模型进程基本概念 进程是程序在一个数据集合上运行的过程(运行的过程&#xff0…

智能驾驶词典 --- 自动驾驶芯片梳理

0 前言 与智能驾驶相关的芯片主要分为自动驾驶芯片(边缘端)和智能座舱芯片两大类,另外衍生的相关芯片种类还有计算集群芯片(云端), 1 自动驾驶芯片梳理 目前业内具有代表性的智驾芯片产品梳理如下。 1…

Studio 3T使用教程,本人详细介绍连接Mongodb过程

1:安装好MongodbWindows下安装 MongoDB_mongodb windows_Dragon-v的博客-CSDN博客2:安装好Studio 3T3:打开 Studio 3T ,点击开始创建连接 4:点击 Manually configure my connection settings,然后next5&…

【MySQL之MySQL底层分析篇】系统学习MySQL,从应用SQL语法到底层知识讲解,这将是你见过最完成的知识体系

文章目录MySQL体系结构MySQL存储结构(以InnoDB为例)MySQL执行流程(以InnoDB为例)1. 数据写入原理2. 数据查询原理MySQL存储引擎1. 为什么需要不同的存储引擎2. 如何为数据指定不同的存储引擎,数据粒度又是多少3. MySQL…

28岁还是一事无成,现在想学习软件测试还来得及吗?

为什么会学习软件测试? 28岁了,算一下8年了,工作了一年,就没去工作就一-直在家,家里固定每个月给2000,偶尔一个月有四千,但依旧没钱,家里给了一套房子,出门200米就是地铁站&#xff…

【流程控制】JavaScript 全栈体系(五)

JavaScript 基础 第七章 运算符 一、赋值运算符 目标: 能够使用赋值运算符简化代码 赋值运算符:对变量进行赋值的运算符 已经学过的赋值运算符: 将等号右边的值赋予给左边, 要求左边必须是一个容器其他赋值运算符: -*/% 使用…

轻松实现内网穿透:实现远程访问你的私人网络

导语:内网穿透是什么?为什么我们需要它?今天我们将介绍这个令人惊叹的技术,让你实现远程访问你的私人网络。 使用内网穿透,轻松实现外网访问本地部署的网站 第一部分:什么是内网穿透? 通俗解释…

【LeetCode】剑指 Offer 18. 删除链表中重复的节点(题目二) p122 -- Java Version

题目链接:https://leetcode.cn/problems/remove-duplicates-from-sorted-list/ 1. 题目介绍(83. 删除排序链表中的重复元素) 给定一个已排序的链表的头 head , 删除所有重复的元素,使每个元素只出现一次 。返回 已排序…

机器学习-BM-FKNCN、BM-FKNN等分类器对比实验

目录 一、简介和环境准备 二、算法简介 2.1四种方法类: 2.1.1FKNN 2.1.2FKNCN 2.1.3BM-FKNN 2.1.3BM-FKNCN 2.2数据预处理 2.3输出视图 2.4调用各种方法看准确率 2.4.1BM-FKNCN 2.4.2BM-FKNN 2.4.3FKNCN 2.4.4FKNN 2.4.5KNN 一、简介和环境准备 k…

Java9之HttpClientAPI实战详解

Java9 之 HttpClientAPI 实战详解 前言 相信关注 java9 的小伙伴们都知道 java9 版本内置模块提供了 Http 功能,当然并不是说之前 jdk 之前并不支持,那么这次更新又多了什么呢?或者是解决了什么问题? 说明 自 JDK 1.0 以来&…

图灵完备及TypeScript图灵完备性验证

一、图灵完备 1.图灵完备的概念 首先从定义出发,什么是图灵完备:图灵完备指一系列操作数据的规则能够模拟任何图灵机。 WikiPedia-图灵完备介绍,在可计算性理论,如果一系列操作数据的规则(如指令集、编程语言、细胞自…

centos安装Anaconda3

目录一、参考二、Anaconda简介1、用途2、关于anaconda三、下载安装1、下载2、安装anaconda3、配置环境遍历4、测试配置结果5、设置显示前缀一、参考 在centos上安装Anaconda 最新Anaconda3的安装配置及使用教程(附图文) 二、Anaconda简介 一句话&…

系统升级丨分享返佣,助力商企实现低成本高转化营销

秉承助力传统经济数字化转型的长远理念 酷雷曼VR再次在VR全景营销中发力 创新研发“分享返佣”功能 进一步拓宽商企VR全景营销渠道 助力商企搭建低成本、高传播、高转化 的VR营销体系 01、什么是“分享返佣”? ●“分享返佣”即“推广”返佣,是酷…

干货满满!MES的简介和运用

导读 谈及MES必须先谈生产,生产体系模型如图所示,涉及人、财、物、信息等资源,产、供、销等环节,以及供应商、客户、合作伙伴等。 其中,生产管理是通过对生产系统的战略计划、组织、指挥、实施、协调、控制等活动&…

【经验总结】10年的嵌入式开发老手,到底是如何快速学习和使用RT-Thread的?(文末赠书5本)

【经验总结】一位近10年的嵌入式开发老手,到底是如何快速学习和使用RT-Thread的? RT-Thread绝对可以称得上国内优秀且排名靠前的操作系统,在嵌入式IoT领域一直享有盛名。近些年,物联网产业的大热,更是直接将RT-Thread这…

信贷系统学习总结(5)—— 简单的风控示例(含代码)

一、背景1.为什么要做风控?目前我们业务有使用到非常多的AI能力,如ocr识别、语音测评等,这些能力往往都比较费钱或者费资源,所以在产品层面也希望我们对用户的能力使用次数做一定的限制,因此风控是必须的!2.为什么要自己写风控?那么多开源的风控组件,为什么还要写呢?是不是想…