面试—多线程

ops/2024/9/20 1:59:54/ 标签: java, jvm, 数据结构

目录

线程的创建方式

线程的生命周期

线程同步的方法

多线程内存可见性

线程安全问题


线程的创建方式

  1. 继承Therad类

    定义一个类继承Therad类

    重写run()方法(线程实际执行的逻辑)

    创建类的对象,调用start()方法开启线程

  2. 实现Runnable接口

    定义一个类实现Runnable接口,并且实例化

    重写run()方法

    创建一个Therad对象,将实现Runnable接口的类作为实参

    调用start()方法开启线程

    • 相较于继承Therad类

    • 在多个线程执行相同逻辑时,继承Thread类需要为每个线程创建一个Therad线程,重复写执行的代码

    • 而实现Runnable接口只需将实现接口的类实例化,作为参数传个Therad类

  3. 实现Callable接口和Future接口

    创建一个类实现Callable接口,接口泛型表示返回值的类型

    重写call()方法

    创建FutureTask对象用于管理返回值(参数为实现Callable接口的实例化对象)

    创建Thread对象用于启动线程(参数为futuerTask对象)

  4. 利用线程池创建

    线程池的七个参数

    1. 核心线程数,即使没有任务,也会有的线程数量

    2. 最大线程数,当任务队列已满且新任务提交时,会创建新线程直到最大值

    3. 空闲时间,当线程数量超过核心线程数时,多余的空闲线程被终止的时间

    4. 空闲时间单位

    5. 阻塞队列

      当队列为空时,获取元素的线程会被阻塞,直到有元素

      当队列已满时,插入元素操作的线程会被阻塞,直到队列中有空间

    6. 线程工厂(创建线程的方式)

      线程工厂(ThreadFactory)是一个用于创建线程的工具接口,接口只有一个方法,接受一个Runnable对象作为参数,表示线程要执行的任务,并返回创建一个Thread对象

    7. 拒绝策略,当任务队列满且线程数量超过最大线程数时,多余任务的处理策略

      终止策略(AbortPolicy)任务无法提交,直接抛出异常

      调用者运行策略(CallerRunsPolicy)由提交这个任务的线程去执行这个任务

      丢弃策略(DiscardPolicy)直接丢弃任务,不抛出异常

      丢弃最旧策略(DiscardOldestPolicy)丢弃队列中最旧的未处理的任务,将新任务加入队列

      new ThreadPoolExecutor.AbortPolicy() // 拒绝策略

线程的生命周期

  • 线程是程序执行的最小单位,是进程中的一个执行路径

  • 多线程是指在一个进程中执行多个线程,每个线程可以独立执行不同的任务

  1. 新建,创建Thread对象时,线程处于新建阶段

  2. 就绪,调用start()方法,线程处于就绪状态,等待CPU分配时间切片(操作系统分配给可执行线程的处理器时间)

  3. 运行,拿到CPU分配的时间切片,执行run()方法里面的代码

  4. 阻塞,当其他线程拿到锁执行代码时,线程处于阻塞状态

  5. 等待,调用wait()方法,线程处于等待状态,等待其他线程调用notify()方法唤醒

  6. 超时等待,当调用sleep(),wait()方法,参数是超时时间,线程进入超时等待状态,如果长时间没有被唤醒,线程会被自动恢复执行

  7. 终止,执行完run()方法里面的代码时,或出现异常,线程会被终止

线程同步的方法

  1. synchronized关键字

    修饰方法时,表示这个方法被加锁,只能由一个线程去执行,其他线程等待这个线程执行完毕释放锁,才能由下一个线程执行

  2. ReentrantLock类

    提供比synchronized更方便的方法,但是需要手动上锁(lock)和释放锁(unlock)

    可以调用tryLock()方法尝试获取锁,如果获取不到就直接返回,不去排队阻塞。

    可以去中断等待的线程,当线程等待锁的过程中被其他线程中断时,会直接中断并抛出异常

    • 采用公平锁,获取锁的顺序按照线程的请求顺序

    • 等待时间可以预测,大致就是上一个线程所运行的时间

  3. CountDownLatch类

    主要用于一个或多个线程等待其他线程

    初始化一个计数器

    当线程执行完代码后调用countDown()方法减少计数器的值

    其他线程会执行awit()方法进入阻塞状态,直到计数器的值为零

    将所有的等待线程释放

  4. 信号量(Semaphore)

    • 用于控制同时访问特定资源的线程数量

    创建一个信号量,设置许可数量

    当线程访问共享资源的时候,会先获取信号量,如果许可数大于0,则可以去访问共享资源,并且许可数减一

    当线程完成对共享资源的操作后,会释放资源,许可数加一。

多线程内存可见性

  • 在多线程环境下,线程之间可能存在缓存,当一个线程对公共变量修改时,其他线程不能马上看到这个修改的值。

  1. volatile 关键字

    volatile关键字修饰的变量可以确保修改后其他线程立即可见

    当变量被修改时,会将修改后的值放入主内存中,其他线程缓存中的变量会失效,当使用变量时,必须从主内存中获取

  2. 使用synchronized关键字或Lock锁

    当线程进入同步代码块或方法中时,会获得一个锁,强制该线程从主内存中获取共享变量,当线程释放锁时,会将修改后的共享变量写回主内存

  3. 使用原子类

    在多线程环境下对单个数据进行原子化操作

    1. 底层处理器会提供原子指令,如CAS指令,当执行CAS指令时,会在内存上发出一个信号,表示内存位置值正在被修改,将其他线程中的缓存副本标记无效,当其他使用共享变量时,从主内存中重新获取变量

      CAS主要有三个参数,内存位置(V)、期望原值(A)、新值(B)

      1. 先读取内存位置中的值(V),作为期望原值(A)

      2. 通过计算得到新值(B)

      3. 再次读取内存位置中的值,与期望原值进行比较

      4. 如果相同,说明值没有被其他线程修改,更新内存位置中的值为计算出来的新值(B)

        如果不同,说明值被修改了,重写读取,直到尝试读取一点的次数或比较相同为止

    2. 内置屏障强制处理器按指定的顺序执行内存操作,并保证不同线程对内存的修改能被其他线程看到(缓存中的变量失效)

    3. 使用乐观锁,当CAS指令出现ABA问题时

      如何一个值从A变为B,在从B变回A,CAS认为这个变量没有被修改过

      这时使用乐观锁的版本号机制,避免ABA问题

线程安全问题

  1. 线程之间抢占执行和随机调度

    • 线程的执行顺序是随机的

    使用synchronized关键字或Lock锁,保证方法和同步代码块由一个线程执行时上锁,其他线程等待

    使用原子类,对数据类型或对象进行原子操作,确保不受线程抢占调度的影响

  2. 多个线程同时修改同一变量

    使用synchronized关键字或Lock锁

  3. 死锁问题

    • 每个线程在持有资源的同时,还在等待另一个线程释放资源

    避免嵌套锁,一个线程拥有一个锁的同时避免再去获取另一个锁。或者采用固定的顺序

  4. 内存可见性

    • 在多线程环境下,一个线程对共享变量修改时,其他线程不能马上看到修改后的变量

    使用volatile关键字,在一个线程修改共享变量后,将修改后的放入主内存中,其他线程中的缓存失效,必须去主内存中获取

  5. 指令重排序

    • 一个线程在执行过程中可能先去执行别的指令,再执行写入操作。如果一个线程里面的数据会依赖另一个线程的数据结果,当CPU调度时,可能第一个线程先执行完,获得的数据不正确(获得初始化的值)

    使用volatile关键字,被修饰的变量在编译器执行的时候限制指令重排序,会按照变量的读写顺序执行


http://www.ppmy.cn/ops/113197.html

相关文章

云计算实训48——k8s环境搭建(详细版)

1.创建主机、设置ip、设置hostname 2.设置免密登录 # 生成私钥 [rootk8s-master ~]# ssh-keygen Generating public/private rsa key pair. Enter file in which to save the key (/root/.ssh/id_rsa): /root/.ssh/id_rsa already exists. Overwrite (y/n)? y Enter passphr…

App结合3D形象的技术实现选择

在为App添加3D人物交互效果时,可以采用多种技术,具体选择取决于你的目标平台(iOS、Android、跨平台)以及项目的复杂性和需求。 以下是几种常用技术及其特点: 游戏引擎技术 游戏引擎提供了强大的3D图形渲染和交互功能&…

区块链学习笔记3--以太坊

智能合约:跑在以太坊系统中的代码合同,其实质是一段代码。目前已经存在180多万个智能合约。 智能合约能表达:规则明确,不受主观因素影响的业务。 智能合约能表达:规则不轻易修改的业务 如果业务的规则经常变化&#x…

【C++】关键字、命名空间、输入和输出、缺省参数的深入了解

目录 一、C关键字二、命名空间2.1 为什么存在命名空间?2.2 命名空间定义2.3 命名空间使用 三、C输入&输出四、缺省函数4.1 缺省函数分类 总结 一、C关键字 C一共有63个关键字 其中红色圈出来的32个关键字同时也是C语言的 二、命名空间 2.1 为什么存在命名空间…

.net core8 使用JWT鉴权(附当前源码)

说明 该文章是属于OverallAuth2.0系列文章,每周更新一篇该系列文章(从0到1完成系统开发)。 该系统文章,我会尽量说的非常详细,做到不管新手、老手都能看懂。 说明:OverallAuth2.0 是一个简单、易懂、功能强…

【Vmware16安装教程】

📖Vmware16安装教程 ✅1.下载✅2.安装 ✅1.下载 官网地址:https://www.vmware.com/ 百度云盘:Vmware16下载 123云盘:Vmware16下载 ✅2.安装 1.双击安装包VMware-workstation-full-16.1.0-LinuxProbe.Com.exe,点击…

requests-html的具体使用方法有哪些?

‌requests-html是一个功能强大的Python库,用于发送HTTP请求和解析HTML内容。它的使用方法包括安装库、基本使用、发送带有参数的请求、图片抓取实战案例、解析网页内容、执行JavaScript代码、使用CSS选择器来查找元素、继续跟踪链接并获取内容等。‌ ‌安装request…

Java语言程序设计基础篇_编程练习题*18.29(某个目录下的文件数目)

题目:*18.29(某个目录下的文件数目) 编写一个程序,提示用户输入一个目录,然后显示该目录下的文件数。 和上一题(18.28)的思路差不多,把找到文件后累加大小到变量变成计数1即可。 Java语言程序设计基础篇_编程练习题*18.28 (非递…

Leetcode Hot 100刷题记录 -Day14(矩阵置0)

矩阵置0 问题描述: 给定一个 m x n 的矩阵,如果一个元素为 0 ,则将其所在行和列的所有元素都设为 0。 示例 1: 输入:matrix [[1,1,1],[1,0,1],[1,1,1]] 输出:[[1,0,1],[0,0,0],[1,0,1]]示例 2:…

STL模板库

一、模板 1、什么是模板 C语言中提供一种自动生成代码的技术,这种技术可以让程序员在编程时不需要考虑数据类型,而专注思考业务逻辑和算法,程序员只需要编写好代码的整体框架,具体的数据类型由使用者提供,这就叫模板…

JavaDS —— 图

图的概念 图是由顶点集合以及顶点之间的关系组成的一种数据结构:G (V,E) 其中 V 表示的是顶点集合 : V { x | x 属于某个数据对象集} 是有穷非空集合 E 叫做边的集合 : E {(x, y) | x, y 属于 V} 或者 …

Python基础语法(3)下

列表和元组 列表是什么,元组是什么 编程中,经常需要使用变量,来保存/表示数据。变量就是内存空间,用来表示或者存储数据。 如果代码中需要表示的数据个数比较少,我们直接创建多个变量即可。 num1 10 num2 20 num3…

【Git原理与使用】版本管理与分支管理(1)

目录 一、基本操作 1、初识Git 2、Git安装[Linux-centos] 3、Git安装[ Linnx-ubuntu] 4、创建git本地仓库 5、配置Git 6、认识工作区、暂存区、版本库 7、添加文件 8、查看历史提交记录 9、查看.git文件目录结构 10、查看版本库对象的内容 11、小结(在本地的.git仓库…

javaMail

在Java程序中发送电子邮件通常依赖于JavaMail API。JavaMail API是Java的一部分,用于发送和接收电子邮件。以下是一个使用JavaMail API发送简单电子邮件的基本步骤和示例代码。 步骤 1: 添加JavaMail依赖 首先,确保你的项目中包含了JavaMail的依赖。如…

Comsol 多孔弹性波应用三:吸声器(超宽频带)

超宽频带吸声材料(Ultra-wideband absorbing materials)是指能够在非常宽的频率范围内吸收声波的材料。传统的吸声材料通常只能在较窄的频率范围内有效吸收声波,而超宽频带吸声材料可以在更广泛的频率范围内实现高效的吸声效果。这使得超宽频…

关于加强银行业保险业移动互联网应用程序管理的通知

近日,国家金融监督管理总局印发《关于加强银行业保险业移动互联网应用程序管理的通知》(下称“《通知》”),指导银行业金融机构、保险业金融机构和金融控股公司(以下统称金融机构)有序规范建设移动互联网应用程序(下称“移动应用”)。 《通知》指出,金融机构应当…

深入理解ConcurrentHashMap

HashMap为什么线程不安全 put的不安全 由于多线程对HashMap进行put操作,调用了HashMap的putVal(),具体原因: 假设两个线程A、B都在进行put操作,并且hash函数计算出的插入下标是相同的; 当线程A执行完第六行由于时间片…

vue本地打包并将构建文件推送到服务器对应目录下

第一步安装依赖 pnpm install node-ssh第二步创建名为deploy.mjs文件 import path from node:path import { fileURLToPath } from node:url import { NodeSSH } from node-sshconst ssh new NodeSSH()async function deploy() {console.log(打包成功进行部署流程)try {// 连…

论文翻译:USENIX-2021 Extracting Training Data from Large Language Models

Extracting Training Data from Large Language Models 从大型语言模型中提取训练数据 https://www.usenix.org/system/files/sec21-carlini-extracting.pdf 文章目录 从大型语言模型中提取训练数据摘要1 引言 摘要 现在,发布在私有数据集上训练的大型&#xff…

828华为云征文 | 深度评测,华为云Flexus X实例在Sysbench性能测试中的亮眼表现

前言 本文章评测了华为云Flexus X实例在Sysbench性能测试中的亮眼表现。Flexus X凭借其新一代处理器和智能算力技术,在CPU、内存、磁盘I/O及网络性能上均展现出了卓越的能力。通过Sysbench的详尽测试,Flexus X实例在多核计算能力、内存吞吐量、磁盘响应速…