当前位置: 首页 > news >正文

【Java并发编程之美 | 第一篇】并发编程线程基础

在这里插入图片描述

文章目录

  • 1.并发编程线程基础
    • 1.1什么是线程和进程?
    • 1.2线程创建与运行
      • 1.2.1继承Thread类
      • 1.2.2实现Runnable接口
      • 1.2.3实现Callable接口(与线程池搭配使用)
      • 1.2.4小结
    • 1.3线程常用方法
      • 1.3.1线程等待与通知
      • 1.3.2线程睡眠
      • 1.3.3让出CPU执行权
      • 1.3.4线程中断
    • 1.4理解线程上下文切换
    • 1.5线程死锁
      • 1.5.1什么是线程死锁?
      • 1.5.2如何避免死锁?

1.并发编程线程基础

1.1什么是线程和进程?

  1. 线程是进程中的一个实体,线程本身是不会独立存在的,线程则是进程的一个执行路径
  2. 进程是系统进行资源分配的基本单位,线程是CPU分配的基本单位
  3. 进程例子:我们在电脑上启动的一个个应用,比如我们启动一个浏览器,就会启动了一个浏览器进程
  4. 线程例子:在 Java 程序中启动的一个 main 函数,即启动了一个JVM进程,而main函数所在的线程就是这个进程中的一个线程,称为主线程

image-20240614185816073

1.2线程创建与运行

  1. Java中创建线程主要有三种⽅式,分别为继承Thread类、实现Runnable接口、实现Callable接口。

1.2.1继承Thread类

  1. 继承Thread类,重写run()⽅法,调⽤start()⽅法启动线程
public class ThreadTest {/*** 继 承Thread类**/public static class MyThread extends Thread {@Overridepublic void run () {System.out.println( "This is child thread" ) ;}}public static void main ( String [] args) {MyThread thread = new MyThread ();thread.start();}
}

1.2.2实现Runnable接口

  1. 实现 Runnable 接口,重写 run() 方法
  2. 然后创建 Thread 对象,将 Runnable 对象作为参数传递给 Thread 对象,调用 start() 方法启动线程。
class RunnableTask implements Runnable {public void run() {System.out.println("上岸、上岸!");}public static void main(String[] args) {RunnableTask task = new RunnableTask();Thread thread = new Thread(task);thread.start();}
}

1.2.3实现Callable接口(与线程池搭配使用)

  1. 实现 Callable 接口,重写 call() 方法
  2. 然后创建 FutureTask 对象,参数为 Callable 对象;紧接着创建 Thread 对象,参数为 FutureTask 对象,调用 start() 方法启动线程。
  3. 通过 实现Callable接口的对象 的get方法获取返回结果
class CallableTask implements Callable<String> {public String call() {return "上岸、上岸了!";}public static void main(String[] args) throws ExecutionException, InterruptedException {CallableTask task = new CallableTask();FutureTask<String> futureTask = new FutureTask<>(task);Thread thread = new Thread(futureTask);thread.start();System.out.println(futureTask.get());}
}

1.2.4小结

image-20240421103020296

1.3线程常用方法

  1. 线程等待方法:wait()、wait(long timeout)、wait(long timeout,int nanos)
  2. 线程通知方法:nodify()、notifyAll()
  3. 让出优先权:yield()
  4. 线程中断方法:interrupt()、isinterrupted()、interrupted()
  5. 线程休眠方法:sleep()

1.3.1线程等待与通知

线程等待方法:

  1. wait():当一个线程 A 调用一个共享变量的 wait() 方法时,线程 A 会被阻塞挂起,直到发生下面几种情况才会返回 :

    1.1 线程 B 调用了共享对象 notify()或者 notifyAll() 方法;

    1.2 其他线程调用了线程 A 的 interrupt()方法,线程 A 抛出 InterruptedException 异常返回。

  2. wait(long timeout) :这个方法相比 wait() 方法多了一个超时参数,它的不同之处在于,如果线程 A 调用共享对象的 wait(long timeout)方法后,没有在指定的 timeout 时间内被其它线程唤醒,那么这个方法还是会因为超时而返回。、

  3. wait(long timeout, int nanos),其内部调用的是 wait(long timout) 方法。

唤醒/通知线程主要有下面两个方法:

  1. notify():一个线程 A 调用共享对象的 notify() 方法后,会唤醒一个在这个共享变量上调用 wait 系列方法后被挂起的线程。一个共享变量上可能会有多个线程在等待,具体唤醒哪个等待的线程是随机的
  2. notifyAll():不同于在共享变量上调用 notify()方法会唤醒被阻塞到该共享变量上的一个线程,notifyAll 方法会唤醒所有在该共享变量上调用 wait 系列方法而被挂起的线程。

join():等待线程执行终止

  1. 如果一个线程 A 执行了 thread.join(),当前线程 A 会被阻塞,即等待 thread 线程执行终止之后才从 thread.join() 返回

1.3.2线程睡眠

  1. sleep(long millis):Thread 类中的静态方法,当一个执行中的线程 A 调用了 Thread 的 sleep 方法后,线程 A 会暂时让出指定时间的执行权
  2. 但是线程 A 所拥有的监视器资源,比如锁,还是持有不让出的。指定的睡眠时间到了后该方法会正常返回,接着参与 CPU 的调度,获取到 CPU 资源后就可以继续运行

1.3.3让出CPU执行权

  1. yield():Thread 类中的静态方法,当一个线程调用 yield 方法时,实际是在暗示线程调度器,当前线程请求让出自己的 CPU

1.3.4线程中断

  1. Java 中的线程中断是一种线程间的协作模式,通过设置线程的中断标志并不能直接终止该线程的执行

  2. void interrupt():中断线程

    2.1 例如:当线程A运行时,线程B可以调用线程A的interrupt()方法来设置线程A的中断标志为true并立即返回

    2.2 设置中断标志仅仅是标记,线程A并没有被中断,会继续往下执行

    2.3 但如果线程A因为调用wait、join、以及sleep方法而被阻塞挂起,这时线程B若调用线程A的interrupt()方法,线程A会在调用这些方法的地方抛出InterrupedException异常

  3. boolean isInterrupted():检测当前线程是否被中断,如果是返回true,否则返回false

  4. boolean interrupted():检测当前线程是否被中断,如果是返回true,否则返回false。与 isInterrupted 不同的是,该方法如果发现当前线程被中断,则会清除中断标志。

1.4理解线程上下文切换

  1. 在多线程编程中,线程个数一般都大于CPU个数,但是每个CPU同一时刻只能被一个线程使用
  2. 为了让用户感觉多个线程是在同时执行,CPU资源的分配采用了时间片轮转的方法,即给每个线程分配一个时间片,线程在时间片内占用CPU执行任务。当线程使用完时间片,就处于就绪状态并让出CPU让其他线程占用,即上下文切换

1.5线程死锁

1.5.1什么是线程死锁?

  1. 死锁是指两个或两个以上的线程在执行过程中,因为争夺资源而造成的互相等待的现象

  2. 产生死锁的四个条件:

    2.1 互斥性:资源是互斥的,同一时刻只能由一个线程占用

    2.2 请求并持有条件:一个线程已经占有一个资源,同时提出新的资源请求,并占据已有的资源不释放

    2.3 不可剥夺条件:线程获取到的资源在自己使用完之前不能被其他线程所占用

    2.4 环路等待条件:指在发生死锁时,必然存在一个线程一资源的环形链

  3. 代码举例:

    import java.util.Date;public class LockTest {public static String obj1 = "obj1";public static String obj2 = "obj2";public static void main(String[] args) {LockA la = new LockA();new Thread(la).start();LockB lb = new LockB();new Thread(lb).start();}
    }
    class LockA implements Runnable{public void run() {try {System.out.println(new Date().toString() + " LockA 开始执行");while(true){synchronized (LockTest.obj1) {System.out.println(new Date().toString() + " LockA 锁住 obj1");Thread.sleep(3000); // 此处等待是给B能锁住机会synchronized (LockTest.obj2) {System.out.println(new Date().toString() + " LockA 锁住 obj2");Thread.sleep(60 * 1000); // 为测试,占用了就不放}}}} catch (Exception e) {e.printStackTrace();}}
    }
    class LockB implements Runnable{public void run() {try {System.out.println(new Date().toString() + " LockB 开始执行");while(true){synchronized (LockTest.obj2) {System.out.println(new Date().toString() + " LockB 锁住 obj2");Thread.sleep(3000); // 此处等待是给A能锁住机会synchronized (LockTest.obj1) {System.out.println(new Date().toString() + " LockB 锁住 obj1");Thread.sleep(60 * 1000); // 为测试,占用了就不放}}}} catch (Exception e) {e.printStackTrace();}}
    }
    
  4. 执行结果:

    image-20240614201836475

1.5.2如何避免死锁?

  1. 只要破坏产生死锁的四大条件中的一个即可,其中破坏环形等待条件最为容易,即保持资源申请的有序性就可以避免死锁

  2. 例子:

    class LockB implements Runnable{public void run() {try {System.out.println(new Date().toString() + " LockB 开始执行");while(true){synchronized (LockTest.obj1) {System.out.println(new Date().toString() + " LockB 锁住 obj2");Thread.sleep(3000); synchronized (LockTest.obj2) {System.out.println(new Date().toString() + " LockB 锁住 obj1");Thread.sleep(60 * 1000); }}}} catch (Exception e) {e.printStackTrace();}}
    }
    

在这里插入图片描述

相关文章:

【Java并发编程之美 | 第一篇】并发编程线程基础

文章目录 1.并发编程线程基础1.1什么是线程和进程&#xff1f;1.2线程创建与运行1.2.1继承Thread类1.2.2实现Runnable接口1.2.3实现Callable接口&#xff08;与线程池搭配使用&#xff09;1.2.4小结 1.3线程常用方法1.3.1线程等待与通知1.3.2线程睡眠1.3.3让出CPU执行权1.3.4线…...

基于python-CNN卷积网络训练识别牛油果和猕猴桃-含数据集+pyqt界面

代码下载地址&#xff1a; https://download.csdn.net/download/qq_34904125/89383066 本代码是基于python pytorch环境安装的。 下载本代码后&#xff0c;有个requirement.txt文本&#xff0c;里面介绍了如何安装环境&#xff0c;环境需要自行配置。 或可直接参考下面博文…...

论文笔记:ATime-Aware Trajectory Embedding Model for Next-Location Recommendation

Knowledge and Information Systems, 2018 1 intro 1.1 背景 随着基于位置的社交网络&#xff08;LBSNs&#xff09;&#xff0c;如Foursquare和Facebook Places的日益流行&#xff0c;大量用户签到数据变得可用 这些大量签到数据的可用性带来了许多有用的应用&#xff0c;以…...

深度学习之---迁移学习

目录 一、什么是迁移学习 二、为什么需要迁移学习&#xff1f; 1. 大数据与少标注的矛盾&#xff1a; 2. 大数据与弱计算的矛盾&#xff1a; 3. 普适化模型与个性化需求的矛盾&#xff1a; 4. 特定应用&#xff08;如冷启动&#xff09;的需求。 三、迁移学习的基本问题有…...

百度网盘限速解决办法

文章目录 开启P2P下载30秒会员下载体验一次性高速下载服务导入“百度网盘青春版”后下载注册新号参与活动 获取下载直链后使用磁力链接下载不是办法的办法无效、已失效方法免限速客户端、老版本客户端、永久会员下载体验试用客户端&#xff0c;或类似脚本、工具获取下载直链后多…...

银河麒麟系统项目部署

使用服务器信息 软件&#xff1a;VMware Workstation Pro 虚拟机&#xff1a;ubtun 内存&#xff1a;20G 虚拟机连接工具&#xff1a; MobaXterm Redis连接工具&#xff1a; RedisDesktopManager 镜像&#xff1a;F:\Kylin-Server-10-8.2-Release-Build09-20211104-X86_64…...

Stable Diffusion【应用篇】【艺术写真】:粘土风之后陶瓷风登场,来看看如何整合AI艺术写真吧

在国外的APP Remini引爆了粘土滤镜后&#xff0c;接着Remini又推出了瓷娃娃滤镜。相当粘土滤镜&#xff0c;个人更喜欢瓷娃娃滤镜&#xff0c;因为陶瓷工艺更符合东方艺术审美。 下面我们就来看看陶瓷特效在AI写真方面的应用。话不多说&#xff0c;我们直接开整。 关于粘土整…...

手机IP地址距离多远会变:解析移动设备的网络定位奥秘

在移动互联网时代&#xff0c;手机IP地址扮演着至关重要的角色&#xff0c;它不仅是我们访问网络的基础&#xff0c;还常常与网络定位、地理位置服务等相关联。那么&#xff0c;手机IP地址在距离多远时会发生变化呢&#xff1f;手机IP地址距离多远会变&#xff1f;下面跟着虎观…...

ChatGPT中文镜像网站分享

ChatGPT 是什么&#xff1f; ChatGPT 是 OpenAI 开发的一款基于生成预训练变换器&#xff08;GPT&#xff09;架构的大型语言模型。主要通过机器学习生成文本&#xff0c;能够执行包括问答、文章撰写、翻译等多种文本生成任务。截至 2023 年初&#xff0c;ChatGPT 的月活跃用户…...

碳化硅陶瓷膜良好的性能

碳化硅陶瓷膜是一种高性能的陶瓷材料&#xff0c;以其独特的物理和化学特性&#xff0c;在众多领域展现出了广泛的应用前景。以下是对碳化硅陶瓷膜的详细介绍&#xff1a; 一、基本特性 高强度与高温稳定性&#xff1a;碳化硅陶瓷膜是一种非晶态陶瓷材料&#xff0c;具有极高的…...

每日一题——Python实现PAT乙级1028 人口普查 Keyboard(举一反三+思想解读+逐步优化)六千字好文

一个认为一切根源都是“自己不够强”的INTJ 个人主页&#xff1a;用哲学编程-CSDN博客专栏&#xff1a;每日一题——举一反三Python编程学习Python内置函数 Python-3.12.0文档解读 目录 题目链接​编辑我的写法 专业点评 时间复杂度分析 空间复杂度分析 总结 我要更强…...

小程序 UI 风格,构建美妙视觉

小程序 UI 风格&#xff0c;构建美妙视觉...

使用Python在VMware虚拟机中模拟Ubuntu服务器搭建网站

在此之前可以先使用VS Code连接到虚拟机&#xff1a;Visual Studio Code连接VMware虚拟机-CSDN博客 安装Web服务器Apache sudo apt-get install apache2 在个别情况下需要对Apache服务器的配置文件进行调整&#xff1a; 打开etc路径下的apache2文件夹&#xff0c;根据端口…...

腾讯测试开发<ieg 实验室>

3.26 40min 自我介绍实习经历有无遇到什么难点&#xff0c;你是如何克服的在这个项目中你大概做了多少个测试用例&#xff0c;这么多测试用例你平时用什么工具进行管理的&#xff0c;每一次跑全部还是每次只跑一部分现在假设给你一个新的项目&#xff0c;需要你这边去做测试&a…...

windows命令帮助大全

有关某个命令的详细信息&#xff0c;请键入 HELP 命令名 ASSOC 显示或修改文件扩展名关联。 ATTRIB 显示或更改文件属性。 BREAK 设置或清除扩展式 CTRLC 检查。 BCDEDIT 设置启动数据库中的属性以控制启动加载。 CACLS 显示或修改文件的访问控制列表(ACL)。 CALL 从另一个批处…...

pytest中失败用例重跑

pip install pytest-rerunfailures 下载rerunfailures插件包 配置文件中加入命令 --reruns 次数 也可在命令行中pytest --rerun-failures2 可以在allure报告中看到重试效果...

http穿透怎么做?

众所周知http协议的默认端口是80&#xff0c;由于国家工信部要求&#xff0c;域名必须备案才给开放80端口&#xff0c;而备案需要固定公网IP&#xff0c;这就使得开放http80端口的费用成本和时间成本变的很高。那么能不能利用内网穿透技术做http穿透呢&#xff1f;下面我就给大…...

前端技术回顾系列 11|TS 中一些实用概念

在微信中阅读,关注公众号:CodeFit。 创作不易,如果你觉得这篇文章对您有帮助,请不要忘了 点赞、分享 和 关注 我的公众号:CodeFit,为我的持续创作提供动力。 上文回顾:泛型在类和接口中的应用 上一篇文章我们回顾了 泛型 在 类 和 接口 中的应用。 通过使用泛型,我们…...

leetcode LRU 缓存

leetcode: LRU 缓存 LRU 全称为 Least Recently Used&#xff0c;最近最少使用&#xff0c;常常用于缓存机制&#xff0c;比如 cpu 的 cache 缓存&#xff0c;使用了 LRU 算法。LRU 用于缓存机制时&#xff0c;关键的是当缓存满的时候有新数据需要加载到缓存的&#xff0c;这个…...

LeetCode 2786.访问数组中的位置使分数最大:奇偶分开记录(逻辑还算清晰的题解)

【LetMeFly】2786.访问数组中的位置使分数最大&#xff1a;奇偶分开记录&#xff08;逻辑还算清晰的题解&#xff09; 力扣题目链接&#xff1a;https://leetcode.cn/problems/visit-array-positions-to-maximize-score/ 给你一个下标从 0 开始的整数数组 nums 和一个正整数 …...

嵌入式仪器模块:音频综测仪和自动化测试软件

• 24 位分辨率 • 192 KHz 采样率 • 支持多种模拟/数字音频信号的输入/输出 应用场景 • 音频信号分析&#xff1a;幅值、频率、占空比、THD、THDN 等指标 • 模拟音频测试&#xff1a;耳机、麦克风、扬声器测试&#xff0c;串扰测试 • 数字音频测试&#xff1a;平板电…...

计算商场折扣 、 判断体重指数 题目

题目 JAVA5 计算商场折扣分析&#xff1a;代码&#xff1a; JAVA6 判断体重指数分析&#xff1a;代码&#xff1a;大佬代码&#xff1a; JAVA5 计算商场折扣 描述 牛牛商场促销活动&#xff1a; 满100全额打9折&#xff1b; 满500全额打8折&#xff1b; 满2000全额打7折&…...

input输入框禁止输入小数点方法

使用blur事件&#xff1a; <el-input v-model"number" type"number" placeholder"请输入" blur"numberBlur" /> 第一种&#xff1a; 使用parseInt转为整数&#xff1a; this.number parseInt(this.number);第二种&#xff…...

使用adb通过wifi连接手机

1&#xff0c;手机打开开发者模式&#xff0c;打开无线调试 2&#xff0c;命令行使用adb命令配对&#xff1a; adb pair 192.168.0.102:40731 输入验证码&#xff1a;422859 3&#xff0c;连接设备&#xff1a; adb connect 192.168.0.102:36995 4&#xff0c;查看连接状态:…...

如何一键拷贝PPT中的所有文字?

有时我们可能需要引用PPT的文字&#xff0c;但一个幻灯片一个幻灯片拷贝很是麻烦&#xff0c;我们想一键拷贝PPT中所有幻灯片中的内容&#xff08;最近我就遇到了这个需求&#xff09;。今天就来讲讲这个一键拷贝的技巧。因为大家可能会遇到同样的问题&#xff0c;所以在此记录…...

Hive的存储格式和压缩算法的特点和选择

1、数据存储格式&#xff1a; ①TEXTFILE HIVE 中默认的存储格式&#xff1b; 一般使用在数据贴源层(ODS 或 STG) &#xff0c;针对需要使用脚本 LOAD 加载数据到 HIVE 数仓表中的情况&#xff1b;需要把表里数据导出或直接可以查看等场景&#xff0c;作为BI供数 易读性…...

C语言中的枚举类型(enum)是如何定义的

在C语言中&#xff0c;枚举类型&#xff08;enum&#xff09;是一种用户定义的数据类型&#xff0c;它允许为整数值指定一个易读的名字。枚举类型通常用于表示固定数量的可能值&#xff0c;例如一周的七天或颜色的集合。 枚举类型的定义使用关键字 enum&#xff0c;后面跟着枚…...

SPI通信协议

一、SPI通信 1、SPI&#xff08;Serial Peripheral Interface&#xff09;是由Motorola公司开发的一种通用数据总线 2、四根通信线&#xff1a;SCK&#xff08;Serial Clock&#xff09;、MOSI&#xff08;Master Output Slave Input&#xff09;、MISO&#xff08;Master In…...

【免费Web系列】大家好 ,今天是Web课程的第二一天点赞收藏关注,持续更新作品 !

这是Web第一天的课程大家可以传送过去学习 http://t.csdnimg.cn/K547r 员工管理 1. 条件分页查询 1.1 概述 在页面原型中&#xff0c;我们可以看到在查询员工信息列表时&#xff0c;既需要根据条件动态查询&#xff0c;还需要对查询的结果进行分页处理。 那要完成这个页面…...

【单片机毕业设计选题24007】-基于STM32和阿里云的家庭健康数据监测系统

系统功能: 本课题设计是基于STM32单片机作为控制主体&#xff0c;通过HX711称重模块&#xff0c;HC-SR04超声波测距模块&#xff0c;红外测温&#xff0c;心率传感器等模块通过I2C或SPI接口与STM32进行通信&#xff0c;并读取传感器输出的身高&#xff0c;体重&#xff0c;心率…...