Java进阶13讲__第12讲_2/2

news/2024/9/17 4:38:54/ 标签: java, 开发语言, 多线程, 线程池, 线程通信, Executor

Ø线程安全问题

Ø线程同步方案

Ø线程池

Ø线程通信

Ø理论补充

1.  线程安全问题

1.1  举例说明

1.2  代码实现

java">package com.itheima.a_线程安全;/*
线程安全:多个线程同时修改同一个资源取钱案例小明和小红是一对夫妻,他们有一个共同的账户,余额是10万元如果小明和小红同时来取钱,并且2人各自都在取钱10万元,可能会出现什么问题呢?实现步骤1. 创建1个账户类,在类中定义账户金额和取钱方法2. 创建1个取钱线程类,在类中调用取钱方法3. 在主线程中创建1个账户对象代表二人的共享账户4. 在主线程中创建2个取钱线程,分别代表小明和小红,并将共享账户对象传递给2个线程处理5. 启动2个线程
*/
public class Demo {//3. 在主线程中创建1个账户对象代表二人的共享账户public static void main(String[] args) {Account account = new Account();//2. 创建1个取钱线程类,在类中调用取钱方法//4. 在主线程中创建2个取钱线程,分别代表小明和小红,并将共享账户对象传递给2个线程处理Person xHong = new Person(account);Person xMing = new Person(account);xMing.setName("小明");xHong.setName("小红");xMing.start();xHong.start();}
}//5. 启动2个线程
class Person extends Thread {private Account account;public Person(Account account) {this.account = account;}@Overridepublic void run() {account.drawMoney(100000);}
}//1. 创建1个账户类,在类中定义账户金额和取钱方法
class Account {private Integer Money = 100000;public void drawMoney(Integer drawMoney) {if (drawMoney <= Money) {System.out.println(Thread.currentThread().getName() + "取钱" + drawMoney + "元成功");Money -= drawMoney;System.out.println(Thread.currentThread().getName() + "余额已更新");System.out.println(Thread.currentThread().getName() + "余额为:" + Money);} else {throw new RuntimeException("账户余额不足");}}
}

2.  线程同步方案

2.1  认识线程同步

2.2  方式一:同步代码块

java">package com.itheima.b_线程同步_同步代码块;
/*
同步代码块把访问共享资源的核心代码给上锁,以此保证线程安全格式synchronized(同步锁){访问共享资源的核心代码}
原理每次只允许一个线程加锁后进入,执行完毕后自动解锁,其他线程才可以进来执行
注意1、对于当前同时执行的线程来说,同步锁必须是同一把(同一个对象),否则会出bug注意2、同步锁不建议随便使用一个唯一的对象,也能锁住,但可能影响无关线程, 建议使用共享资源作为锁对象对于实例方法建议使用this作为锁对象规范对于静态方法建议使用字码(类名.class) 对象作为锁对象
*/
public class Account {//账户余额private Integer balance = 100000;//取钱public void drawMoney(Integer money) {//0.获取线程名称//1. 判断余额是否充足synchronized (this) {if (money > balance) {System.out.println(Thread.currentThread().getName() + "取钱失败,余额不足");return;//方法结束}//2. 如果够,出钱System.out.println(Thread.currentThread().getName() + "取钱成功");//3. 更新余额balance -= money;System.out.println(Thread.currentThread().getName() + "取钱之后余额为:" + balance);}}
}

2.3  方式二:同步方法

java">package com.itheima.c_线程同步_同步方法;
/*
同步方法把访问共享资源的核心方法给上锁,以此保证线程安全。格式修饰符 synchronized 返回值类型 方法名称(形参列表) {操作共享资源的代码}
原理每次只允许一个线程加锁后进入,执行完毕后自动解锁,其他线程才可以进来执行同步方法其实底层也是有隐式锁对象的,只是锁的范围是整个方法代码。如果方法是实例方法:同步方法默认用this作为的锁对象。如果方法是静态方法:同步方法默认用类名.class作为的锁对象。
*/
public class Account {//账户余额private Integer balance = 100000;//取钱public synchronized void drawMoney(Integer money) {//0.获取线程名称//1. 判断余额是否充足if (money > balance) {System.out.println(Thread.currentThread().getName() + "取钱失败,余额不足");return;//方法结束}//2. 如果够,出钱System.out.println(Thread.currentThread().getName() + "取钱成功");//3. 更新余额balance -= money;System.out.println(Thread.currentThread().getName() + "取钱之后余额为:" + balance);}
}

2.4  方式三:Lock锁

java">package com.itheima.d_线程同步_lock锁;import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;/*
Lock锁概述Lock锁是JDK5开始提供的一个新的锁定操作,通过它可以创建出锁对象进行加锁和解锁,更灵活、更方便、更强大Lock是接口,不能直接实例化,可以采用它的实现类ReentrantLock来构建锁对象
方法public ReentrantLock() 创建锁对象public void lock()    上锁public void unlock() 释放锁
Lock锁使用规范规范1、锁对象创建在成员位置,使用final修饰规范2、释放锁的代码写在finally块中
*/
public class Account {//账户余额private Integer balance = 100000;private final Lock lock = new ReentrantLock();//取钱public void drawMoney(Integer money) {//0.获取线程名称String threadName = Thread.currentThread().getName();lock.lock();try {//1. 判断余额是否充足if (money > balance) {System.out.println(threadName + "取钱失败,余额不足");return;//方法结束}//2. 如果够,出钱System.out.println(Thread.currentThread().getName() + "取钱成功");//3. 更新余额balance -= money;System.out.println(Thread.currentThread().getName() + "取钱之后余额为:" + balance);} catch (Exception e) {e.printStackTrace();} finally {lock.unlock();}}
}

2.5  三种线程同步方法对比

3.  线程池

3.1  认识线程池

3.1.1  定义 

3.1.2  线程池工作原理

3.1.3  线程池的执行流程

3.2  如何创建线程池

3.3  线程池处理Runnable任务

java">package com.itheima.e_线程池;import java.util.concurrent.*;/*
线程池一个可以复用线程的技术
执行流程(核心线程-->工作队列-->临时线程-->拒绝策略)判断核心线程数是否已满,如果没满,则创建一个新的核心线程来执行任务如果核心线程满了,则判断工作队列是否已满,如果没满,则将任务存储在这个工作队列如果工作队列满了,则判断最大线程数是否已满,如果没满,则创建临时线程执行任务如果最大线程数已满,则执行拒绝策略
对象创建接口 ExecutorService实现类 ThreadPoolExecutorint corePoolSize : 指定线程池的核心线程的数量int maximumPoolSize:指定线程池的最大线程数量long keepAliveTime :指定临时线程的存活时间TimeUnit unit:指定临时线程存活的时间单位BlockingQueue<Runnable> workQueue:指定线程池的任务队列ThreadFactory threadFactory:指定线程池的线程工厂RejectedExecutionHandler handler:指定线程池的任务拒绝策略
*/
public class Demo1 {public static void main(String[] args) {ExecutorService es = new ThreadPoolExecutor(3,5,60,TimeUnit.SECONDS,new ArrayBlockingQueue(5),Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());System.out.println(es);//核心线程es.execute(() -> {System.out.println(Thread.currentThread().getName());System.out.println("执行任务");try {Thread.sleep(25000);} catch (InterruptedException e) {throw new RuntimeException(e);}});es.execute(() -> {System.out.println(Thread.currentThread().getName());System.out.println("执行任务");try {Thread.sleep(25000);} catch (InterruptedException e) {throw new RuntimeException(e);}});es.execute(() -> {System.out.println(Thread.currentThread().getName());System.out.println("执行任务");try {Thread.sleep(25000);} catch (InterruptedException e) {throw new RuntimeException(e);}});//等待队列es.execute(() -> {System.out.println(Thread.currentThread().getName());System.out.println("执行任务");});es.execute(() -> {System.out.println(Thread.currentThread().getName());System.out.println("执行任务");});es.execute(() -> {System.out.println(Thread.currentThread().getName());System.out.println("执行任务");});es.execute(() -> {System.out.println(Thread.currentThread().getName());System.out.println("执行任务");});es.execute(() -> {System.out.println(Thread.currentThread().getName());System.out.println("执行任务");});//临时线程es.execute(() -> {System.out.println(Thread.currentThread().getName());System.out.println("执行任务");try {Thread.sleep(25000);} catch (InterruptedException e) {throw new RuntimeException(e);}});es.execute(() -> {System.out.println(Thread.currentThread().getName());System.out.println("执行任务");try {Thread.sleep(25000);} catch (InterruptedException e) {throw new RuntimeException(e);}});es.execute(() -> {System.out.println(Thread.currentThread().getName());System.out.println("执行任务");});System.out.println(es);//提交多次任务
//        for (int i = 0; i < 10; i++) {
//            es.execute(new Runnable() {
//                @Override
//                public void run() {
//                    System.out.println(Thread.currentThread());
//                    System.out.println("执行任务");
//                }
//            });
//        }}
}

3.4  线程池处理Callable任务

java">package com.itheima.e_线程池;import java.util.concurrent.*;/*
线程池执行Runnable任务Future<T> submit(Callable<T> task)	执行Callable任务,返回未来任务对象,用于获取线程返回的结果void shutdown()  等全部任务执行完毕后,再关闭线程池!List<Runnable> shutdownNow() 立刻关闭线程池,停止正在执行的任务,并返回队列中未执行的任务
*/
public class Demo3 {public static void main(String[] args) throws Exception {ExecutorService es = new ThreadPoolExecutor(3,5,60,TimeUnit.SECONDS,new ArrayBlockingQueue(5),Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());System.out.println(es);Future<Integer> future = es.submit(() -> {int count = 0;for (int i = 0; i < 11; i++) {if (i % 2 == 0) {//遇到偶数休眠两秒Thread.sleep(2000);}count += i;}return count;});
//        System.out.println("count:" + future.get());System.out.println("count:" + future.get(5, TimeUnit.SECONDS));}
}

案例

java">package com.itheima.e_线程池;import java.util.concurrent.*;/*
线程池执行Runnable任务Future<T> submit(Callable<T> task)	执行Callable任务,返回未来任务对象,用于获取线程返回的结果void shutdown()  等全部任务执行完毕后,再关闭线程池!List<Runnable> shutdownNow() 立刻关闭线程池,停止正在执行的任务,并返回队列中未执行的任务
*/
public class Demo3 {public static void main(String[] args) throws Exception {ExecutorService es = new ThreadPoolExecutor(3,5,60,TimeUnit.SECONDS,new ArrayBlockingQueue(5),Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());System.out.println(es);Future<Integer> future = es.submit(new MyTask(10));System.out.println(future.get());Future<Integer> future1 = es.submit(new MyTask(5));System.out.println(future1.get());Future<Integer> future2 = es.submit(new MyTask(100));System.out.println(future2.get());es.shutdown();System.out.println(es);}
}//需求: 编写一个任务类, 可以通过构造器接收n, 计算并返回1~n的和
class MyTask implements Callable<Integer> {private int n;public MyTask(int n) {this.n = n;}/*** 计算1-n的和** @return* @throws Exception*/@Overridepublic Integer call() throws Exception {int sum = 0;for (int i = 1; i <= n; i++) {sum += i;}return sum;}
}

3.5  Executors工具类实现线程池

面试可能会问,了解

4.  线程通信(了解)

5.  理论补充

5.1  进程与线程

5.2  并发与并行

5.2.1  并发

5.2.2  并行

5.3  线程生命周期


http://www.ppmy.cn/news/1523327.html

相关文章

《React Native 应用开发最佳实践》

⭐️React Native 应用开发最佳实践⭐️ 近年来&#xff0c;React Native 应用开发因其能够使用 JavaScript 构建原生移动应用的能力而大受欢迎。它提供了跨平台兼容性、更快的开发时间以及更易于维护的特性&#xff0c;成为了许多开发者的首选。然而&#xff0c;要确保 React…

免费的 Mac 应用清理工具Pearcleaner v3.8.6

免费的 Mac 应用清理工具。这是一款免费开源的 Mac 应用清理工具&#xff0c;能够彻底卸载应用并清理残留文件。它采用 SwiftUI 开发&#xff0c;提供了简单易用的界面&#xff0c;支持右键卸载、迷你模式和 Homebrew 清理等功能。 下载链接&#xff1a;https://pan.quark.cn/s…

计算机网络(三) —— 简单Udp网络程序

目录 一&#xff0c;初始化服务器 1.0 辅助文件 1.1 socket函数 1.2 填充sockaddr结构体 1.3 bind绑定函数 1.4 字符串IP和整数IP的转换 二&#xff0c;运行服务器 2.1 接收 2.2 处理 2.3 返回 三&#xff0c;客户端实现 3.1 UdpClient.cc 实现 3.2 Main.cc 实现 …

前端面试热点题目——typescript篇

在TypeScript面试中&#xff0c;面试官通常会考察你对TypeScript特性的理解、类型系统的掌握、以及在实际项目中的应用能力。以下是一些热点题目及其相应的代码示例&#xff0c;旨在帮助你准备TypeScript相关的面试。 1. 类型别名与接口的区别及使用场景 问题&#xff1a;请解…

react js 笔记 3

起因&#xff0c; 目的: 专注。 学习 react js 的时候&#xff0c; 就专注这一方面 &#xff0c;其他都不要碰。 比如&#xff0c; python, C语言&#xff0c; R, 都不看。 只看 js.专注&#xff0c;减少来回切换。 重复。 自己写的笔记&#xff0c;需要反复多看几遍&#xff…

java开发后端

1.BeanUtils.toBean 方法 它是一个常见的 Java 工具方法&#xff0c;用于将一个 JavaBean 对象转换为另一个 JavaBean 对象 FlowOrderDO flowOrder BeanUtils.toBean(createReqVO, FlowOrderDO.class); 这行代码使用了 BeanUtils.toBean 方法&#xff0c;它是一个常见的 Ja…

MySQL笔记2(DQL查询语言【条件、分组、排序、限制、子查询、左右连接、内连接、联合查询】)

DQL数据查询语言与项目高级查询实战 先安装数据库并创建一个库 并创建以下数据 /*创建部门表*/CREATE TABLE dept( deptnu INT PRIMARY KEY comment 部门编号, dname VARCHAR(50) comment 部门名称, addr VARCHAR(50) comment 部门地址 );/*某个公司的员工表*/ CREATE TABLE…

html备忘录

备忘录 网站收藏数据&#xff1a; 网站收藏.js const webLinks [{ title: "智能翻译", src: "https://fanyi.baidu.com" },{ title: "哔哩哔哩", src: "https://www.bilibili.com" },{ title: "百度一下&#xff0c;你就知道&…

漫谈设计模式 [9]:外观模式

引导性开场 菜鸟&#xff1a;老鸟&#xff0c;我最近在做一个项目&#xff0c;感觉代码越来越复杂&#xff0c;我都快看不懂了。尤其是有好几个子系统&#xff0c;它们之间的调用关系让我头疼。 老鸟&#xff1a;复杂的代码确实让人头疼。你有没有考虑过使用设计模式来简化你…

微信支付开发避坑指南

1 微信支付的坑 1.1 不能用前端传递过来的金额 订单的商品金额要从数据库获取&#xff0c;前端只传商品 id。 1.2 交易类型trade type字段不要传错 v2版API&#xff0c;不同交易类型&#xff0c;要调用的支付方式也不同。 1.3 二次签名 下单时&#xff0c;在拿到预支付交…

记录深度学习量化操作

0. 简介 深度学习中做量化提升运行速度是最常用的方法&#xff0c;尤其是大模型这类非常吃GPU显存的方法。一般是高精度浮点数表示的网络权值以及激活值用低精度&#xff08;例如8比特定点&#xff09;来近似表示达到模型轻量化&#xff0c;加速深度学习模型推理&#xff0c;目…

MySQL表的操作与数据类型

目录 前言 一、表的操作 1.创建一个表 2.查看表的结构 3.修改表 4.删除一个表 二、 MySQL的数据类型 0.数据类型一览&#xff1a; 1.整数类型 2.位类型 3.小数类型 4.字符类型 前言 在MySQL库的操作一文中介绍了有关MySQL库的操作&#xff0c;本节要讲解的是由库管理的结构——…

TinyWebSever源码逐行注释(三)_ thread_pool.cpp

前言 项目源码地址 项目详细介绍 项目简介&#xff1a; Linux下C轻量级Web服务器&#xff0c;助力初学者快速实践网络编程&#xff0c;搭建属于自己的服务器. 使用 线程池 非阻塞socket epoll(ET和LT均实现) 事件处理(Reactor和模拟Proactor均实现) 的并发模型使用状态机…

python基础语法四-数据可视化

书接上回&#xff1a; python基础语法一-基本数据类型 python基础语法二-多维数据类型 python基础语法三-类 1. plot函数绘制简单折线图 (1)需要的模块&#xff1a;matplotlib.pyplot (2)语法&#xff1a;matplotlib.pyplot.plot(x, y, format_string, **kwargs) x: x轴数…

C语言程序设计-练习篇

不知道结果仍义无反顾地才是勇士。 三&#xff0c;打印整数二进制的奇数位和偶数位 题目内容&#xff1a; 获取一个整数二进制序列中所有的奇数位和偶数位&#xff0c;分别打印出二进制序列 #include <stdio.h>//打印整数二进制的奇数位和偶数位 int main() {int i 0…

C语言从头学55——学习头文件errno.h、float.h

1、头文件 errno.h 中的变量 errno 的使用 在 errno.h 定义了一个 int 类型的变量 errno&#xff08;错误码&#xff09;&#xff0c;如果发现这个变量出现非零值&#xff0c;表示已经执行的函数发生了错误。这个变量一般多用于检查数学函数运算过程中发生的错误。 …

Vue面试题——项目介绍以及SPA介绍

谈谈你开发的项目背景与、架构和技术栈 项目背景 假设我们正在开发一个名为“智慧旅游助手”的Web平台。该平台旨在为用户提供一站式的旅游服务&#xff0c;包括目的地推荐、酒店预订、行程规划、在线购票&#xff08;如门票、机票&#xff09;、旅游攻略分享以及基于地理位置…

不到200行代码,一键写出简单贪吃蛇网页游戏!附详细代码!快来看看吧!

​哈喽大家好&#xff0c;这里是大白百宝阁&#xff0c;每天分享一段小代码~ 今天要分享的是&#xff0c;不到200行代码&#xff0c;制作html版贪吃蛇&#xff0c;效果如下&#xff1a; 游戏结束后&#xff0c;还会显示&#xff1a; 代码如下&#xff1a; <!DOCTYPE html&g…

传统CV算法——边缘算子与图像金字塔算法介绍

边缘算子 图像梯度算子 - Sobel Sobel算子是一种用于边缘检测的图像梯度算子&#xff0c;它通过计算图像亮度的空间梯度来突出显示图像中的边缘。Sobel算子主要识别图像中亮度变化快的区域&#xff0c;这些区域通常对应于边缘。它是通过对图像进行水平和垂直方向的差分运算来…

基于Java+SpringBoot+Vue+MySQL的美容美发管理系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、SSM项目源码 系统展示 基于SpringBootVue的美容美发管理系统【附源码文档】、前后…