【Java基础 下】 029 -- 多线程

news2025/7/20 21:24:19

目录

一、为什么要有多线程?

1、线程与进程

2、多线程的应用场景

3、小结

二、多线程中的两个概念(并发和并行)

1、并发

2、并行

3、小结

三、多线程的三种实现方式

1、继承Thread类的方式进行实现

2、实现Runnable接口的方式进行实现

3、利用Callable接口和Future接口方式的实现

4、多线程三种实现方式对比

四、常见的成员方法

1、get/setName方法 -- 线程名字

2、currentThread方法 -- 获取当前线程对象

3、sleep方法 -- 线程休眠

4、set/getPriority方法 -- 线程优先级

5、setDaemon方法 -- 守护线程

6、yield方法 -- 礼让线程

7、join方法 -- 插入线程

8、线程的生命周期

五、线程安全的问题

1、练习:设计一个程序模拟电影院卖票

2、买票引发的安全问题

①、重复票的由来:(线程在执行代码的过程中,CPU的执行权随时有可能被抢走)

②、出现了超出范围的票:(和上面的原因相同)

3、安全问题的解决办法 -- 同步代码块

4、同步代码块中的两个小细节

①、细节1:synchronized要写在循环的里面

②、细节2:synchronized中的锁对象一定是唯一的

5、同步方法

6、StringBuilder和StringBuffer的区别

7、Lock锁(手动加锁、释放锁)

①、Lock使用不规范造成的两个安全问题

六、死锁

七、生产者和消费者(等待唤醒机制)

1、消费者等待

2、生产者等待

3、常见方法(wait/notify/notifyAll)

4、消费者与生产者代码实现

①、Cook.java

②、Desk.java

③、Foodie.java

④、ThreadDemo.java

5、阻塞队列方式(另一种等待唤醒机制)

①、阻塞队列的继承结构

②、阻塞队列实现等待唤醒机制

7、多线程的6中状态

八、综合练习

1、多线程练习1(卖电影票)

2、多线程练习2(送礼品)

3、多线程练习3(打印奇数数字)

4、多线程练习4(抢红包)

精确运算:(BigDecimal)

5、多线程练习5(抽奖箱抽奖)

6、多线程练习6(多线程统计并求最大值)

7、多线程练习7(多线程之间的比较)

8、多线程练习8(多线程阶段大作业)

九、线程池

1、吃饭买碗的故事

①、问题

②、解决方案

2、以前写多线程的弊端

3、线程池的核心原理

4、线程池的代码实现

①、Executors工具类

②、线程复用示例

③、创建一个有上限的线程池

5、自定义线程池(ThreadPoolExecutor)

①、任务拒绝策略

②、代码实现

③、小结

6、最大并行数

①、什么是最大并行数?

②、向Java虚拟机返回可用处理器的数目

7、线程池多大才合适?

十、多线程的额外扩展内容


一、为什么要有多线程?

1、线程与进程

举例:在任务管理器中,一个软件运行之后,它就是一个进程

线程:(简单理解,线程就说应用软件中互相独立,可以同时运行的功能)

单线程程序:所有的都在一个线程中执行,耗时长

2、多线程的应用场景

3、小结

二、多线程中的两个概念(并发和并行)

1、并发

2、并行

以2核4线程为例:(如果计算机中只要4条线程,那么它是不用切换的,但如果线程越来越多,那么这个红线就会在多个线程之间随机的进行切换)

3、小结

三、多线程的三种实现方式

1、继承Thread类的方式进行实现

代码实现:

①、自己定义一个类继承Thread并重写run方法

②、创建子类的对象,并启动线程

2、实现Runnable接口的方式进行实现

代码实现:

①、自己定义一个类实现Runnable接口,并重新里面的run方法

②、创建自己的类对象

③、创建一个Thread类的对象,并开启线程

示例代码:

3、利用Callable接口和Future接口方式的实现

代码实现:

①、创建一个类MyCallable实现Callable接口,并重写call

②、创建MyCallable/FutureTask/Thread的对象

完整代码:

4、多线程三种实现方式对比

四、常见的成员方法

1、get/setName方法 -- 线程名字

默认名字的由来:

序号自增

细节:

2、currentThread方法 -- 获取当前线程对象

3、sleep方法 -- 线程休眠

4、set/getPriority方法 -- 线程优先级

抢占式调度:随机性

非抢占式调度:轮流

没有设置,优先级则默认为5,优先级越高,抢到CPU的概率就越高

示例代码:

5、setDaemon方法 -- 守护线程

两个线程执行的代码不同:守护线程是陆续结束的,所以守护线程也叫做备胎线程

守护线程的应用场景:

6、yield方法 -- 礼让线程

但只是尽可能的均匀,不是绝对的

7、join方法 -- 插入线程

插入线程:将土豆插入到main线程之前,只有当土豆线程执行完毕,才会轮到main线程

8、线程的生命周期

五、线程安全的问题

1、练习:设计一个程序模拟电影院卖票

示例代码:

出现了超出票范围或者重复票的情况:

2、买票引发的安全问题

①、重复票的由来:(线程在执行代码的过程中,CPU的执行权随时有可能被抢走)

②、出现了超出范围的票:(和上面的原因相同)

3、安全问题的解决办法 -- 同步代码块

示例代码:(锁对象一定得是唯一的)

4、同步代码块中的两个小细节

①、细节1:synchronized要写在循环的里面

②、细节2:synchronized中的锁对象一定是唯一的

示例代码:(当前类的字节码文件对象)

5、同步方法

示例代码:

将同步代码块改成同步方法:

6、StringBuilder和StringBuffer的区别

两个类的方法都是相同的

但是StringBuffer是线程安全的,它里面所有的方法都是线程同步的

StringBuilder是非线程安全的,所以如果用到多线程则可以使用StringBuffer,没有需求则选择StringBuilder

7、Lock锁(手动加锁、释放锁)

①、Lock使用不规范造成的两个安全问题

Ⅰ、重复票以及超出范围票

我们在使用Thread类实现多线程时,创建自己的类,一定要注意锁对象需要唯一,即在相关变量前加上static关键字

Ⅱ、程序无法正常终止

这是由于当满足条件时,循环直接被终止,导致lock锁没有被释放

Ⅲ、正确代码(标准写法)

即将容易产生异常的代码块放入try…catch中

六、死锁

死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。

代码实现:(理解过程)

注意事项:千万不要让两个锁嵌套起来!

七、生产者和消费者(等待唤醒机制)

生产者消费者模式是一个十分经典的多线程协作的模式

1、消费者等待

2、生产者等待

3、常见方法(wait/notify/notifyAll)

4、消费者与生产者代码实现

①、Cook.java

②、Desk.java

③、Foodie.java

④、ThreadDemo.java

5、阻塞队列方式(另一种等待唤醒机制)

①、阻塞队列的继承结构

②、阻塞队列实现等待唤醒机制

Cook.java:

put方法的源码中实现了Lock锁

Foodie.java:

take方法的底层也是有锁的

ThreadDemo.java:

打印语句是在锁的外面的,但是不会对数据造成影响,只是影响了控制台的打印阅读体验

7、多线程的6中状态

Java中是没有定义运行状态的,只有以下6种状态,这是因为一旦线程抢夺到CPU执行权之后,线程就会交给操作系统了,Java就不管了

八、综合练习

1、多线程练习1(卖电影票)

待补充~

2、多线程练习2(送礼品)

待补充~

3、多线程练习3(打印奇数数字)

待补充~

4、多线程练习4(抢红包)

示例代码:

测试类:

精确运算:(BigDecimal)

5、多线程练习5(抽奖箱抽奖)

示例代码:

MyThread.java:

测试类:

6、多线程练习6(多线程统计并求最大值)

示例代码一:(在练习5的基础上进行修改)

MyThread.java:

示例代码二:升级版--线程栈(示例一可以用,但不好)

改进后,这里只需要一个ArrayList就搞定了

示例二内存图讲解:

每个线程都有自己独立的空间

7、多线程练习7(多线程之间的比较)

示例代码:(难点在于如何获取两个线程中的最大值★)

调用多线程的第三种方式Callable来实现(可以返回结果)

MyCallable.java:

测试类:

8、多线程练习8(多线程阶段大作业)

待补充~

 

九、线程池

1、吃饭买碗的故事

①、问题

②、解决方案

买个碗柜,买了碗之后不摔,存入碗柜中

2、以前写多线程的弊端

3、线程池的核心原理

当有新的任务出现,且线程池线程不足时,会新建线程以满足需求,其中最大线程的数量可以自行设置

4、线程池的代码实现

①、Executors工具类

示例代码:

MyRunnable.java:

测试类:

②、线程复用示例

测试类:

③、创建一个有上限的线程池

测试类:

5、自定义线程池(ThreadPoolExecutor)

①、任务拒绝策略

以下面示例为例,它会将任务4抛弃,将任务10加入

②、代码实现

③、小结

6、最大并行数

①、什么是最大并行数?

②、向Java虚拟机返回可用处理器的数目

7、线程池多大才合适?

可以通过thread dump来计算CPU的计算时间和等待时间

十、多线程的额外扩展内容

准备面试时可以再突击学习,资料可见《多线程(额外扩展).md》

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

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

相关文章

MySQL简述

一、什么是数据库 数据库(DB,DataBase) 概念:数据仓库,相当于一款软件,安装在操作系统(Windows,Linux,mac,…)之上,可以存储大量的数…

nvm安装及使用(win)

一、安装nvm 下载地址:下载之后安装包安装 安装路径不要有中文或者空格 安装时尽量不要选择系统盘(安装在系统盘可能会涉及到权限问题) 安装前一定要把 node 的环境变量和 npm 的环境变量删除,否则在切换 node 版本时会报错 二、…

SCL_PFENET跑通填坑

1.数据准备:VOC2012数据集,initmodel文件夹(预训练模型),SegmentationClassAug数据2.训练部分:训练部分没什么需要改动的,也就改一下选择的配置文件。在config文件夹里有关于coco和voc数据的配置…

备战蓝桥杯Day3python——迭代器的使用

python封装的迭代器 我们接下来介绍用于返回笛卡尔积的Permutations函数 Permutations(iterator, r) r:表示进行迭代后返回的长度 实例: >>> from itertools import permutations >>> a abc >>> for i in permutations(a,3):print …

Java深拷贝,浅拷贝

一、浅拷贝: (1) 对于数据类型是基本数据类型的成员变量,浅拷贝会直接进行值传递,也就是将该属性复制一份给新的对象。因为是两份不同的数据,所以对其中一的对象的成员变量值进行修改,不会影响另…

大考在即 百度版ChatGPT会翻车吗?

文心一言的发布会定档3月16日,不出意外,百度创始人李彦宏、CTO王海峰将出现在北京总部的发布会现场。这是百度版ChatGPT最新的官方消息,2月7日,文心一言首次官宣,当时称,产品“3月见”。 3月如期而至&…

C语言再学习 -- __attribute__详解

一、attribute 介绍 __attribute__是一个编译属性,用于向编译器描述特殊的标识、错误检查或高级优化。它是GNU C特色之一,系统中有许多地方使用到。__attribute__可以设置函数属性(Function Attribute)、变量属性(Var…

JavaScript 如何优雅地获取多层级response中的某个深层次字段 ?. 可选链条(Optional chaining)

文章目录一句话场景:从一个多层级对象中拿一个处在深层次位置的字段MDN 可选链搜索引擎使用一句话 var marriedFlag response.data.userList[0].married; // 如果中间某个对象为空,会报Errorvar marriedFlag response?.data?.userList[0]?.married…

外贸新手找客户的开发信修炼之旅(一)

开发信是一种传统的开发海外客户的方式,相信即便是外贸新手也或多或少有所耳闻,甚至已经通过邮件开发到了一些有意向的客户,但有时也会遇到开发信效果不好的情况,收到的回复寥寥无几。其实说白了开发信的本质与派发传单相同&#…

李开复已经对美图公司失去耐心,并在美图公司身上损失惨重

来源:猛兽财经 作者:猛兽财经 猛兽财经经过对美图公司(01357)的投资人回报、产品、业务结构、战略、财务业绩、估值等方面进行了研究,认为美图这家公司不行,非常不看好,以下是理由供你参考。一…

10 Seata配置Nacos注册中心和配置中心

Seata配置Nacos注册中心和配置中心 Seata支持注册服务到Nacos,以及支持Seata所有配置放到Nacos配置中心,在Nacos中统一维护; 高可用(集群)模式下就需要配合Nacos来完成: 具体配置如下 注册中心 Seata-server端配置注册中心,…

【洛谷 P1219】[USACO1.5]八皇后 Checker Challenge 题解(深度优先搜索+回溯法)

[USACO1.5]八皇后 Checker Challenge 题目描述 一个如下的 666 \times 666 的跳棋棋盘,有六个棋子被放置在棋盘上,使得每行、每列有且只有一个,每条对角线(包括两条主对角线的所有平行线)上至多有一个棋子。 上面的布…

13_MySQL中的约束

目录 1. 约束(constraint)概述 1.1 为什么需要约束 1.2 什么是约束 1.3 约束的分类 2. 非空约束 2.1 作用 2.2 关键字 2.3 特点 2.4 添加非空约束 2.5 删除非空约束 3. 唯一性约束 3.1作用 3.2 关键字 3.3 特点 3.5 关于复合唯一约束 4. 主键(PRIMARY KEY)约束 4.1 作用 4.2 关…

【Django】Hello,DJango!

Halo,这里是Ppeua。平时主要更新C语言,C,数据结构算法......感兴趣就关注我吧!你定不会失望。 🌈个人主页:主页链接 🌈算法专栏:专栏链接 我会一直往里填充内容哒! &…

如何实现报表可视化,有没有工具推荐

随着数据量的不断增长,如何更好地进行数据分析和可视化已成为企业和组织面临的重要挑战。实现报表可视化是一个很好的解决方案,它可以帮助用户更好地理解和分析数据,发现趋势和模式,并支持数据驱动的决策。本文将介绍如何实现报表…

现代卷积神经网络(NiN),并使用NIN训练CIFAR10的分类

专栏:神经网络复现目录 本章介绍的是现代神经网络的结构和复现,包括深度卷积神经网络(AlexNet),VGG,NiN,GoogleNet,残差网络(ResNet),稠密连接网络…

【3.7】Redis数据类型、CPU缓存一致性、哈希表

文章目录数据类型篇StringListHashSetZsetBitMapHyperLogLogGEOStreamCPU 缓存一致性CPU是如何执行任务的?什么是软中断?为什么0.1 0.2不等于0.3?哈希表数据类型篇 String String 是最基本的 key-value 结构,key 是唯一标识&…

03 | 授权服务:授权码和访问令牌的颁发流程是怎样的? 笔记

03 | 授权服务:授权码和访问令牌的颁发流程是怎样的? 授权服务的工作过程 小兔软件需要去到京东的平台那里”备案“注册,京东商家开放平台就会给小兔软件 app_id 和 app_secret 等信息,以方便后面授权时的各种身份校验&#xff0…

scratch绘制雷达 电子学会图形化编程scratch等级考试三级真题和答案解析2022年9月

目录 scratch绘制雷达 一、题目要求 1、准备工作 2、功能实现 二、案例分析

阶段二12_面向对象高级_继承1

一.继承的入门介绍 (1)继承的概念理解 让类与类之间产生关系(子父类关系),子类可以直接使用父类中非私有的成员 (2)通过extends关键字实现继承 格式:public class 子类名 extends 父类名 { } 范例:public class Zi e…