【并发编程 | 第一篇】线程相关基础知识

1.并发和并行有什么区别

并发是指多核CPU上的多任务处理,多个任务在同一时刻真正同时执行。

并行是指单核CPU上的多任务处理,多个任务在同一时间段内交替执行,通过时间片轮转实现交替执行,用于解决IO密集型瓶颈。

如何理解线程安全呢?

如果一段代码块或者一个方法被多个线程同时并发执行,其中的共享内容还能够有序正确的执行,就说明是线程安全的。

线程安全满足三个要素:

原子性:一个操作如果执行要么成功,要么失败,不会只执行一部分。

可以通过同步关键字 synchronized 或原⼦操作,如 AtomicInteger 来保证原子性。

可见性:当一个线程修改共享变量后,其他变量可以及时看到。

可以通过 volatile 关键字来保证可⻅性。

有序性:确保线程不会因为死锁、饥饿、活锁等问题导致无法继续执行。

2.线程和进程的区别

进程:进程简单点说就是我们的电脑上启动的一个个应用,它是操作系统分配资源的最小单位。

线程:线程是进程中的独立执行单元。多个线程可以共享一个进程的资源,如内存,每个线程都有自己独立的栈和寄存器。

线程间是如何进行通信的?

原则上可以通过消息传递和共享内存两种⽅法来实现。

Java 采用的是共享内存的并发模型。 这个模型被称为 Java 内存模型,简写为 JMM,它决定了⼀个线程对共享变量的写入,何时对另外⼀个线程可见。 当然了,本地内存是 JMM 的⼀个抽象概念,并不真实存在。

用一句话来概括就是:共享变量存储在主内存中,每个线程的私有本地内存,存储的是这个共享变量的副本。

线程A和线程B之间要通信,有两个步骤:

1、线程A把本地内存A中的共享变量副本刷新到主内存中。

2、线程 B 到主内存中读取线程 A 刷新过的共享变量,再同步到⾃⼰的共享变量副本中。

3.线程有几种创建方式?

有三种,继承Thread类、实现Runnable接口、实现Callable接口。

第一种需要重写父类的run()方法,并调用start()方法启动线程。

class ThreadTask extends Thread {

        public void run() {

                System.out.println("我是继承Thread类创建多线程");

      }

        public static void main(String[] args) {

                ThreadTask task = new ThreadTask();

                task.start();

        }

}

这种继承Thread类创建线程的方法缺点是,如果该类已经继承其他类,就不能继承Thread类了,因为Java是不支持多重继承的。

第二种实现Runnable接口并重写run()方法, 并且将实现类的对象作为参数传递给Thread类的构造方法,最后调用start()方法开启线程。

class RunnableTask implements Runnable {

public void run() {

        System.out.println("我是通过实现Runnable接口创建多线程");

}

public static void main(String[] args) {

                RunnableTask task = new RunnableTask();

                Thread thread = new Thread(task);

                 thread.start();

        }

}

这种方法的优点是避免了Java的单继承的限制,且更加符合面向对象的编程思想,因为Runnable接口将任务代码和线程控制的代码解耦了。

第三种实现Callable接口并重写call()方法,创建FutureTask对象,参数为实现Callable接口的示例对象,然后创建Thread对象,参数为FutureTask对象,最后调用start()方法启动线程。

class CallableTask implements Callable {

public String call() {

        return "我是通过实现Callable接口来创建多线程";

 }

public static void main(String[] args) throws ExecutionException, InterruptedException {

        CallableTask task = new CallableTask();

        FutureTask futureTask = new FutureTask<>(task);

        Thread thread = new Thread(futureTask);

        thread.start();

        System.out.println(futureTask.get());

        }

}  

这种⽅法的优点是可以获取线程的执⾏结果。

启动一个Java程序,你能说说里面有哪些线程吗? 

首先是main线程,这是程序执行的入口

垃圾回收线程,它是一个后台线程,负责回收不再使用的对象

编译器线程,如JIT,负责把一部分热点代码编译后放到codeCache

调用start()方法可以执行run()方法,为什么不直接调用run()方法?

当调用start()方法时,会创建一个新的线程,并异步执行run()方法。

如果直接调用run()方法,就是一个普通方法的调用,不会创建新的线程,会在当前线程下直接执行,也就无法达到多线程的目的了。

也就是说,调用start() ⽅法会通知 JVM,去调⽤底层的线程调度机制来启动新线程。

调用start()方法后,线程处于就绪状态,等待底层操作系统调度,一旦调度执行,就会执行run()方法中的内容。

4.线程中有哪些常用的调度方法?

如start()启用线程等待操作系统调度执行,sleep()让线程休眠一段时间,wait()会让当前线程进入等待,notify()会唤醒一个正在等待的线程。

讲讲wait和notify方法

当线程 A 调⽤共享对象的 wait() ⽅法时,线程 A 会被阻塞挂起,直到线程 B 调用了共享对象的 notify() 方法或者 notifyAll() 方法;

其他线程调用线程A的interrupt() ⽅法,导致线程 A 抛出 InterruptedException 异常。

线程 A 调用共享对象的 wait(timeout) ⽅法后,没有在指定的 timeout 时间内被其它线程唤醒,那么这个方法会 因为超时而返回。

当线程 A 调⽤共享对象的 notify() ⽅法后,会唤醒⼀个在这个共享对象上调用wait 系列方法被挂起的线程。

共享对象上可能会有多个线程在等待,具体唤醒哪个线程是随机的。

讲讲sleep方法

当线程A调用了Thread的sleep方法后,线程A会暂时让出指定时间的执行权。

指定的睡眠时间到了之后,线程A会继续参与执行权的争夺。

讲讲yield方法

yield方法是让当前线程让出CPU的使用权,回到就绪状态。但是线程调度器可能会忽略。

讲讲Interrupt方法

interrupt() 方法用于通知线程停⽌,但不会直接终⽌线程,需要线程自行处理中断标志。 常与 isInterrupted() 或 Thread.interrupted() 配合使用。

5.线程有几种状态?

一般6种,new代表线程创建并未启动,runnable代表线程处于就绪或正在运行的状态,由操作系统调度,blocked代表线程被阻塞,可能是获取锁失败,waiting代表等待线程的通知timed_waiting

代表线程等待一段时间,超时会自动恢复,terminated 代表线程执⾏完毕,生命周期结束。

也就是说,线程的周期可以分为五个阶段:新建,就绪,运行,阻塞,终止。线程运行时会根据状态的变化来随时变化。

通过一个表格对线程状态的总结:

状态说明
NEW当线程被创建后,如通过new Thread(),它处于新建状态。此时,线程已经被分配了必要的资源,但还没有开始执⾏
RUNNABLE当调⽤线程的start()⽅法后,线程进⼊可运⾏状态。在这个状态下,线程可能正在运 ⾏也可能正在等待获取 CPU 时间⽚,具体取决于线程调度器的调度策略。
BLOCKED线程在试图获取⼀个锁以进⼊同步块/⽅法时,如果锁被其他线程持有,线程将进⼊阻塞 状态,直到它获取到锁
WAITING线程进⼊等待状态是因为调⽤了如下⽅法之⼀:Object.wait()或 LockSupport.park()。在等待状态下,线程需要其他线程显式地唤醒,否则不会⾃动 执⾏
TIME_WAITING当线程调⽤带有超时参数的⽅法时,如Thread.sleep(long millis)、 Object.wait(long timeout) 或LockSupport.parkNanos(),它将进⼊超时等待状 态。线程在指定的等待时间过后会⾃动返回可运⾏状态。
TERMINATED当线程的run()⽅法执⾏完毕后,或者因为⼀个未捕获的异常终⽌了执⾏,线程进⼊终止状态。⼀旦线程终⽌,它的⽣命周期结束,不能再被重新启动。

 

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

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

相关文章

Kafka 偏移量

在 Apache Kafka 中&#xff0c;偏移量&#xff08;Offset&#xff09;是一个非常重要的概念。它不仅用于标识消息的位置&#xff0c;还在多种场景中发挥关键作用。本文将详细介绍 Kafka 偏移量的核心概念及其使用场景。 一、偏移量的核心概念 1. 定义 偏移量是一个非负整数…

18.redis基本操作

Redis(Remote Dictionary Server)是一个开源的、高性能的键值对(Key-Value)存储数据库,广泛应用于缓存、消息队列、实时分析等场景。它以其极高的读写速度、丰富的数据结构和灵活的应用方式而受到开发者的青睐。 Redis 的主要特点 ​高性能: ​内存存储:Redis 将所有数…

历年跨链合约恶意交易详解(一)——THORChain退款逻辑漏洞

漏洞合约函数 function returnVaultAssets(address router, address payable asgard, Coin[] memory coins, string memory memo) public payable {if (router address(this)){for(uint i 0; i < coins.length; i){_adjustAllowances(asgard, coins[i].asset, coins[i].a…

通俗易懂的讲解SpringBean生命周期

&#x1f4d5;我是廖志伟&#xff0c;一名Java开发工程师、《Java项目实战——深入理解大型互联网企业通用技术》&#xff08;基础篇&#xff09;、&#xff08;进阶篇&#xff09;、&#xff08;架构篇&#xff09;清华大学出版社签约作家、Java领域优质创作者、CSDN博客专家、…

深入理解 `git pull --rebase` 与 `--allow-unrelated-histories`:区别、原理与实战指南

&#x1f680; git pull --rebase vs --allow-unrelated-histories 全面解析 在日常使用 Git 时&#xff0c;我们经常遇到两种拉取远程代码的方式&#xff1a;git pull --rebase 和 git pull --allow-unrelated-histories。它们的区别是什么&#xff1f;各自适用哪些场景&…

Matlab_Simulink中导入CSV数据与仿真实现方法

前言 在Simulink仿真中&#xff0c;常需将外部数据&#xff08;如CSV文件或MATLAB工作空间变量&#xff09;作为输入信号驱动模型。本文介绍如何高效导入CSV数据至MATLAB工作空间&#xff0c;并通过From Workspace模块实现数据到Simulink的精确传输&#xff0c;适用于运动控制…

Spring Boot 中 JdbcTemplate 处理枚举类型转换 和 减少数据库连接的方法 的详细说明,包含代码示例和关键要点

以下是 Spring Boot 中 JdbcTemplate 处理枚举类型转换 和 减少数据库连接的方法 的详细说明&#xff0c;包含代码示例和关键要点&#xff1a; 一、JdbcTemplate 处理枚举类型转换 1. 场景说明 假设数据库存储的是枚举的 String 或 int 值&#xff0c;但 Java 实体类使用 enu…

API 安全之认证鉴权

作者&#xff1a;半天 前言 API 作为企业的重要数字资源&#xff0c;在给企业带来巨大便利的同时也带来了新的安全问题&#xff0c;一旦被攻击可能导致数据泄漏重大安全问题&#xff0c;从而给企业的业务发展带来极大的安全风险。正是在这样的背景下&#xff0c;OpenAPI 规范…

MATLAB绘图配色包说明

本栏目将分享MATLAB数据分析图表&#xff0c;该贴讲述配色包的使用 将配色包colormap_nclCM文件夹添加到路径close all&#xff08;尽量不要删&#xff09;&#xff0c;使用map colormap(nclCM(309))时会多出来一张空白图片。配色资源来自slandarer&#xff1b;找不到合适颜色…

Oracle 数据库系统全面详解

Oracle 数据库是全球领先的关系型数据库管理系统(RDBMS)&#xff0c;由 Oracle 公司开发。它为企业级应用提供了高性能、高可用性、安全性和可扩展性的数据管理解决方案。 目录 一、Oracle 数据库体系结构 1. 物理存储结构 主要组件&#xff1a; 存储层次&#xff1a; 2. …

Flink介绍——发展历史

引入 我们整个大数据处理里面的计算模式主要可以分为以下四种&#xff1a; 批量计算&#xff08;batch computing&#xff09; MapReduce Hive Spark Flink pig流式计算&#xff08;stream computing&#xff09; Storm SparkStreaming/StructuredStreaming Flink Samza交互计…

在MFC中使用Qt(四):使用属性表(Property Sheet)实现自动化Qt编译流程

前言 首先回顾下前面文章介绍的&#xff1a; 在MFC中使用Qt&#xff08;一&#xff09;&#xff1a;玩腻了MFC&#xff0c;试试在MFC中使用Qt&#xff01;&#xff08;手动配置编译Qt&#xff09; 在MFC中使用Qt&#xff08;二&#xff09;&#xff1a;实现Qt文件的自动编译流…

Go红队开发— 收官工具

文章目录 免责声明个人武器开发美观输出Whois查询反查ip目录扫描子域名爆破被动扫描主动扫描(字典爆破)CDN检测 免责声明 &#x1f4a1; 本博客绝不涉及任何非法用途。 &#x1f4a1; 使用者风险自担&#xff0c;违规后果自负。 &#x1f4a1; 守法为先&#xff0c;技术向善。 …

论文阅读《P​roximal Curriculum for Reinforcement Learning Agents》——提升智能体学习速度的

老规矩&#xff0c;今天是使用Gemini2.5pro来生成的模板 这篇论文研究了如何为处理多个相关任务的强化学习智能体自动设计学习课程&#xff08;即任务顺序&#xff09;&#xff0c;以加速训练过程&#xff0c;并解决现有方法需要大量调参或缺乏理论依据的问题。为此&#xff0…

【面试题】在 CSS 中,实现一个 div 中的子 div 水平垂直居中

1. 使用 Flexbox 特点&#xff1a;简单、直观&#xff0c;现代浏览器支持良好。 代码&#xff1a; css .parent {display: flex;justify-content: center; /* 水平居中 */align-items: center; /* 垂直居中 */height: 200px; /* 父容器需有高度 */ } .child {…

基于SpringBoot的失物招领平台(源码+数据库)

476基于SpringBoot的失物招领平台&#xff0c;有用户和管理员两个角色&#xff0c;主要功能如下 失物招领系统功能介绍如下&#xff1a; 1. 用户功能&#xff1a; - 发布失物公告&#xff1a;用户可以发布自己的失物信息 - 失物分类&#xff1a;用户可以根据失物的类型进行分类…

PyQt6实例_批量下载pdf工具_批量pdf网址获取

目录 前置&#xff1a; 步骤&#xff1a; step one 安装包 step two 获取股票代码 step three 敲代码&#xff0c;实现 step four 网址转pdf网址 视频 前置&#xff1a; 1 本系列将以 “PyQt6实例_批量下载pdf工具”开头&#xff0c;放在 【PyQt6实例】 专栏 2 本节讲…

量子退火与机器学习(2):少量实验即可找到新材料,黑盒优化➕量子退火

使用量子退火和因子分解机设计新材料 这篇文章是东京大学的一位博士生的毕业论文中的主要贡献。 结合了黑盒优化和量子退火&#xff0c;是融合的非常好的一篇文章&#xff0c;在此分享给大家。 https://journals.aps.org/prresearch/abstract/10.1103/PhysRevResearch.2.0133…

从零开始:Makefile 与 CMake 的基础入门与实践

本文适合基础学者 零基础 makefile 定义&#xff1a;Makefile 是一种传统的构建工具&#xff0c;用于定义如何编译和链接源代码。它通过一系列规则来描述如何生成目标文件&#xff08;如可执行文件或库&#xff09;。 功能&#xff1a;定义编译规则&#xff08;如如何从源文件…

android开启Sys V IPC,并使用共享内存编程

参考&#xff1a;安卓开启Sys V IPC&#xff0c;并使用共享内存编程 | 久奈浜的CS部 删除config中-# CONFIG_SYSVIPC is not set 在rk3576.config中增加CONFIG_SYSVIPCy CONFIG_SYSVIPCy CONFIG_SYSVIPC_SYSCTLy CONFIG_SYSVIPC_COMPATy CONFIG_IPC_NSy system/sepolicy/pre…