Java第二十章多线程
一、线程简介
线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位。一个进程可以包含多个线程,这些线程可以并发执行。线程拥有自己的栈和局部变量,但是它们共享进程的其他资源,如全局变量、堆内存等。线程的优先级决定了线程需要时间片多少分配的线程属性。线程的启动和终止需要通过构造线程对象和调用start()方法来实现。
二、创建线程
1、继承Thread类
Thread类是java.lang包中的一个类,从这个类中实例化的对象代表线程,程序员启动一个新线程需要建立Thread实例。Thread类中常用的两个构造方法如下:
1.public Thread():创建一个新的线程对象。
2.public Thread(String threadName):创建一个名称为threadName的线程对象。
继承Thread类创建一个新的线程的语法如下:
public class ThreadTest extends Thread{
}
完成线程真正的功能的代码放在类的run()方法中,当一个类继承Thread类后,就可以在该类中覆盖run()方法,将实现该线程功能的代码写入run()方法中,然后调用Thread类中的start()方法执行线程,也就是调用run方法。
Thread对象需要一个人物来执行,任务是指线程在启动时执行的工作,该工作的功能代码被写在run方法中。run()方法必须使用以下语法格式:
public void run(){
}
注意:start()方法调用一个已经启动的线程,系统将抛出IllegalThreadStateException异常。
当执行一个线程程序时,就自动产生一个线程,主方法正是在这个线程上运行的。当不再启动其他线程时,该程序就为单线程程序,如本章以前的程序都是单线程程序。主方法线程启动由Java虚拟机负责,程序员负责启动自己的线程。代码如下:
public static void main(String[] args){new ThreadTest().start();
}
例题:让线程循环打印1~10的数字
start()方法会启动线程,线程自动执行run()方法中的代码,就可以看到for循环打印的数字了。
在main()方法中,使线程执行需要调用Thread类中的start()方法,start()方法调用被覆盖的run()方法,如果不调用start()方法,线程永远都不会启动,在主方法没有调用start()方法之前,Thread对象只是一个实例,而不是一个真正的线程。
2、实现Runnable接口
例题:让窗口中的图标动起来
三、线程的生命周期
线程具有生命周期,其中包含 7 种状态,分别为出生状态、就绪状态、运行状态、等待状态、眠状态、阻塞状态和死亡状态。出生状态就是线程被创建时处于的状态,在用户使用该线程实例调用start0方法之前线程都处于出生状态;当用户调用 start()方法后,线程处于就绪状态 (又被称为可执状态);当线程得到系统资源后就进入运行状态。
一旦线程进入可执行状态,它会在就绪与运行状态下转换,同时也有可能进入等待、休眠、阻塞或死亡状态。当处于运行状态下的线程调用 Thread 类中的wait0方法时,该线程便进入等待状态,进入等待状态的线程必须调用Thread类中的notify()方法才能被唤醒,而调用notifvAll()方法可将所有处于等待状态下的线程唤醒;当线程调用 Thread 类中的sleep()方法时,则会进入休眠状态。如果一个线程在运行状态下发出输入/输出请求,该线程将进入阻塞状态,在其等待输入/输出结束时线程进入就绪状态,对于阻塞的线程来说,即使系统资源空闲,线程依然不能回到运行状态。当线程的run()方法执行完毕时,线程进入死亡状态。
四、操作线程的方法
1、线程的休眠
一种能控制线程行为的方法是调用sleep()方法,sleep()方法需要一个参数用于指定该线程休眠的时间,该时间以毫秒为单位。在前面的实例中,已经演示过sleep()方法,它通常是在run()方法内的循环中被使用。sleep()方法的语法如下:
try{Thread.sleep(2000);
}catch(InterruptedException e){e.printStackTrace();
}
上述代码会使线程在2秒之内不会进入就绪状态。由于sleep()方法的执行有可能抛出InterruptedException异常,所以将sleep()方法的调用放在try-catch块中。虽然使用了sleep()方法的线程在一段时间内会醒来,但是并不能保证它醒来后进入运行状态,只能保证它进入就绪状态。
例题:每0.1秒绘制一条随机颜色的线条
在本实例中定义了 getC()方法,该方法用于随机产生 Color 类型的对象并且在产生线程的匿名内部类中使用 getGraphics()方法获取 Graphics 对象,使用该对象调用setColor0方法为图形设置颜色。调用 drawLine()方法绘制一条线段,同时线段会根据纵坐标的变化自动调整。
2、线程的加入
如果当前某程序为多线程程序,假如存在一个线程 A,现在需要插入线程 B,并要求线程B先执行完毕,然后再继续执行线程A,此时可以使用 Thread 类中的 join()方法来完成。这就好比此时读者正在看电视,突然有人上门收水费,读者必须付完水费后才能继续看电视。
当某个线程使用 join()方法加入另外一个线程时,另一个线程会等待该线程执行完毕后再继续执行。下面来看一个使用 join()方法的实例。
例题:让进度条A等待进度条B
3、线程的中断
以往有的时候会使用stop()方法停止线程,但当前版本的JDK早已废除了stop()方法,不建议使用stop()=方法来停止一个线程的运行。现在提倡在run()方法中使用无限循环的形式,然后使用一个布尔型标记控制循环的停止。
如果线程是因为使用了sleep()或wait()方法进入了就绪状态,可以使用Thread类中interrupt()方法使线程离开run()方法,同时结束线程,但程序会抛出InterruptedException异常,用户可以在处理该异常时完成线程的中断业务处理,如终止while循环。
例题:单击按钮停止进度条滚动
4、线程的礼让
Thread类中提供了一种礼让方法,使用yield()方法表示,它只是给当前正处于运行状态的线程一个提醒,告知它可以将资源礼让给其他线程,但这仅是一种暗示,没有任何一种机制保证当前线程会将资源礼让。
yield()方法使具有同样优先级的线程有进入可执行状态的机会,在当前线程放弃执行权时会再度回到就绪状态。对于支持多任务的操作系统来说,不需要调用yield()方法,因为操作系统会为线程自动分配CPU时间片来执行。
五、线程的优先级
例题:观察不同优先级的线程执行完毕顺序
由于线程的执行顺序是由CPU决定的,即使线程设定了优先级也是作为CPU的参考数据,所以真实的运行结果可能并不一定按照优先级排序,例如笔者运行的结果如上。执行顺序为:D>C>B>A
六、线程同步
1、线程安全
实际开发中,使用多线程程序的情况很多,如银行排号系统、火车站售票系统等。这种多线程的程序通常会发生问题,以火车站售票系统为例,在代码中判断当前票数是否大于0,如果大于0则执行将该票出售给乘客的功能,但当两个线程同时访问这段代码时(假如这时只剩下一张票),第一个线程将票售出,与此同时第二个线程也已经执行完成判断是否有票的操作,并得出票数大于0的结论,于是它也执行售出操作,这样就会产生负数。所以,在编写多线程程序时,应该考虑到线程安全问题实质上线程安全问题来源于两个线程同时存取单一对象的数据。
例如,在项目中创建ThreadSafeTest类,该类实现了Runnable接口,在未考虑到线程安全问题的基础上,模拟火车站售票系统的功能的代码如下:
2、线程同步机制
例题:开发线程安全的火车售票系统
同步方法就是在方法前面用synchronized关键字修饰的方法,其语法如下:
synchronized void f(){}
当某个对象调用了同步方法时,该对象上的其他同步方法必须等待该同步方法执行完毕后才能被执行。必须将每个能访问共享资源的方法修饰为synchronized,否则就会出错。
修改例20.7的代码,将共享资源操作放置在一个同步方法中,代码如下:
nt num = 10:
public synchronized void doit() {//定义同步方法if(num>0){try{Thread.sleep(10);}catch(InterruptedException e){e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"————票数"+num--);}
}
public void run(){while(true){doit();} //在run()方法中调用该同步方法
}
相关文章:

Java第二十章多线程
一、线程简介 线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位。一个进程可以包含多个线程,这些线程可以并发执行。线程拥有自己的栈和局部变量,但是它们共享进程的其他资源,如…...
家庭教育,培养娃什么最重要?
家庭教育,培养娃什么最重要? 培养能力最重要 (我这么认为的) 时代巨变,技术变革的非常快,所以总的来说 年轻一代接触的新东西慢慢比老一代的要多,年轻一代的工作会比老一代的多而且多很多&…...

Linux 进程(一)
1 操作系统 概念:任何计算机系统都包含一个基本的程序集合,称为操作系统(OS)。笼统的理解,操作系统包括 内核(进程管理,内存管理,文件管理,驱动管理) 其他程序(例…...
vue中的keep-alive详解与应用场景
🌈个人主页:前端青山 🔥系列专栏:Vue篇 🔖人终将被年少不可得之物困其一生 依旧青山,本期给大家带来vue篇专栏内容:vue-keep-alive 目录 一、Keep-alive 是什么 二、使用场景 三、原理分析 四、案例实现 activa…...

软件设计师——程序设计语言基础(一)
📑前言 本文主要是【程序设计语言基础】——程序设计语言基础的相关题目,如果有什么需要改进的地方还请大佬指出⛺️ 🎬作者简介:大家好,我是听风与他🥇 ☁️博客首页:CSDN主页听风与他 &#…...
Apache简介与安装
先导概念: 静态网站: 最早的建站方式,每个页面都是一个独立的文件,需要手动上传或编辑。网页内容固定不变。例如,个人博客、静态企业官网等。 动态网站: 网站内容可根据不同情况动态变更,一般通过数据库进行架构。包含服务器端脚本,可以实现更丰富的功能。例如,社…...

set与map
set与map 一、序列式容器与关联式容器二、pair1、键值对2、作用3、构造函数4、make_pair(1)构造函数(2)作用 5、代码6、运行结果 三、set1、概念2、代码3、运行结果4、说明 四、multiset1、与set的关系2、代码3、运行结果 五、map…...

基于单片机智能液位水位监测控制系统
**单片机设计介绍, 基于单片机智能液位水位监测控制系统 文章目录 一 概要特点应用场景工作原理实现方式 系统功能实时监测控制调节报警功能数据记录与分析 总结 二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 ## 系统介绍 基于单片机…...

C#,《小白学程序》第十七课:随机数(Random)第四,移动平均值(Moving Average)的计算方法与代码
1 文本格式 /// <summary> /// 《小白学程序》第十七课:随机数(Random)第四,移动平均值的计算方法与代码 /// 继续学习数据统计,移动平均值的计算方法 /// 移动平均值就是一定步长内数值的平均值,用…...

行情分析——加密货币市场大盘走势(11.29)
大饼已经形成了底背离,即MACD往下走,而价格还在往上走,这种后续往往会大跌。继续把空单拿好,已经持仓的无需加仓。多次上涨却一直不能突破,说明多空和空军力量都很强,等待后续出方向。在笔者看来࿰…...
C++——string的字符串比较,字符存取,插入和删除和子串
一. string字符串比较 功能描述:字符串之间的比较 比较方式:字符串比较是按字符的ASCII码进行对比 返回 0 > 返回 1 < 返回 -1 函数原型: *int compare(const string &s) const; //与字符串s比较 *int compare(const char *s) const; //…...

字节10年经验之谈 —— 从0到1开发自动化测试框架!
一、序言 随着项目版本的快速迭代、APP测试有以下几个特点: 首先,功能点多且细,测试工作量大,容易遗漏;其次,代码模块常改动,回归测试很频繁,测试重复低效;最后&#x…...
Mysql(基本介绍+下载安装+服务器+基本使用+建库建表+navicat/mybitas工具+外键及实例)
一、Mysql基本介绍 当谈论MySQL时,通常指的是一个流行的开源关系型数据库管理系统(RDBMS)。MySQL是由瑞典的开发者在1995年创建的,后来被Sun Microsystems收购,最终成为Oracle Corporation的一部分。以下是关于MySQL的…...

Python+requests+Jenkins接口自动化测试实例
在做功能测试的基础上,我平时也会用postman测试接口,不过postman只能测试一个一个接口,不能连贯起来,特别是我们公司的接口很多都是要用到token的,导致我每次测个需要登录的接口都要去获取到token,做了很多…...

SpringBoot3核心原理
SpringBoot3核心原理 事件和监听器 生命周期监听 场景:监听应用的生命周期 可以通过下面步骤自定义SpringApplicationRunListener来监听事件。 ①、编写SpringApplicationRunListener实现类 ②、在META-INF/spring.factories中配置org.springframework.boot.Sprin…...
JS常用数据类型转换(数字型和字符串型之间转换)
提供了5中基本数据类型:数字 number 字符串 string 布尔 boolean 空值 null 未定义的 undefined 常用的是数字型和字符串型之间的转换,常用的转换方法如下: 1 数字型转换成字符串型 a) 使用String()方法…...

算法通关村第一关—青铜挑战—用Java基本实现各种链表操作
文章目录 第一关—链表【青铜挑战】1.1 单链表的概念1.2 链表的相关概念1.3 创建链表 - Java实现1.4 链表的增删改查1.4.1 遍历单链表 - 求单链表长度1.4.2 链表插入 - 三种位置插入(1)在链表的表头插入(2)在链表的中间插入&#…...

SparkRDD及算子-python版
RDD相关知识 RDD介绍 RDD 是Spark的核心抽象,即 弹性分布式数据集(residenta distributed dataset)。代表一个不可变,可分区,里面元素可并行计算的集合。其具有数据流模型的特点:自动容错,位置…...

嵌入式设备与PC上位机通信协议设计的几点原则
嵌入式设备在运行中需要设置参数,这个工作经常由PC机来实现,需要为双方通信设计协议,有代表性协议是如下三种: 从上表可以看到,一般嵌入式设备内存和运算性能都有限,因此固定二进制是首选通信协议。 一&am…...

Go 内置运算符
一、算数运算符 1、算数运算符使用 package mainimport ("fmt" )func main(){fmt.PrintIn("103",103) //10313fmt.PrintIn("10-3",10-3) //10-37fmt.PrintIn("10*3",10*3) //10*330//除法注意:如果运算的数都是…...

linux arm系统烧录
1、打开瑞芯微程序 2、按住linux arm 的 recover按键 插入电源 3、当瑞芯微检测到有设备 4、松开recover按键 5、选择升级固件 6、点击固件选择本地刷机的linux arm 镜像 7、点击升级 (忘了有没有这步了 估计有) 刷机程序 和 镜像 就不提供了。要刷的时…...

人机融合智能 | “人智交互”跨学科新领域
本文系统地提出基于“以人为中心AI(HCAI)”理念的人-人工智能交互(人智交互)这一跨学科新领域及框架,定义人智交互领域的理念、基本理论和关键问题、方法、开发流程和参与团队等,阐述提出人智交互新领域的意义。然后,提出人智交互研究的三种新范式取向以及它们的意义。最后,总结…...

华为OD机考-机房布局
import java.util.*;public class DemoTest5 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseSystem.out.println(solve(in.nextLine()));}}priv…...

2025年渗透测试面试题总结-腾讯[实习]科恩实验室-安全工程师(题目+回答)
安全领域各种资源,学习文档,以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具,欢迎关注。 目录 腾讯[实习]科恩实验室-安全工程师 一、网络与协议 1. TCP三次握手 2. SYN扫描原理 3. HTTPS证书机制 二…...

如何应对敏捷转型中的团队阻力
应对敏捷转型中的团队阻力需要明确沟通敏捷转型目的、提升团队参与感、提供充分的培训与支持、逐步推进敏捷实践、建立清晰的奖励和反馈机制。其中,明确沟通敏捷转型目的尤为关键,团队成员只有清晰理解转型背后的原因和利益,才能降低对变化的…...
深度学习之模型压缩三驾马车:模型剪枝、模型量化、知识蒸馏
一、引言 在深度学习中,我们训练出的神经网络往往非常庞大(比如像 ResNet、YOLOv8、Vision Transformer),虽然精度很高,但“太重”了,运行起来很慢,占用内存大,不适合部署到手机、摄…...

ZYNQ学习记录FPGA(一)ZYNQ简介
一、知识准备 1.一些术语,缩写和概念: 1)ZYNQ全称:ZYNQ7000 All Pgrammable SoC 2)SoC:system on chips(片上系统),对比集成电路的SoB(system on board) 3)ARM:处理器…...

PydanticAI快速入门示例
参考链接:https://ai.pydantic.dev/#why-use-pydanticai 示例代码 from pydantic_ai import Agent from pydantic_ai.models.openai import OpenAIModel from pydantic_ai.providers.openai import OpenAIProvider# 配置使用阿里云通义千问模型 model OpenAIMode…...
13.10 LangGraph多轮对话系统实战:Ollama私有部署+情感识别优化全解析
LangGraph多轮对话系统实战:Ollama私有部署+情感识别优化全解析 LanguageMentor 对话式训练系统架构与实现 关键词:多轮对话系统设计、场景化提示工程、情感识别优化、LangGraph 状态管理、Ollama 私有化部署 1. 对话训练系统技术架构 采用四层架构实现高扩展性的对话训练…...
背包问题双雄:01 背包与完全背包详解(Java 实现)
一、背包问题概述 背包问题是动态规划领域的经典问题,其核心在于如何在有限容量的背包中选择物品,使得总价值最大化。根据物品选择规则的不同,主要分为两类: 01 背包:每件物品最多选 1 次(选或不选&#…...