JUC并发编程-线程和进程、Synchronized 和 Lock、生产者和消费者问题

1、什么是JUC

源码 + 官方文档 面试高频问!

在这里插入图片描述

java.util 工具包、包、分类

业务:普通的线程代码 Thread Runnable

Runnable 没有返回值、效率相比入 Callable 相对较低!

在这里插入图片描述
在这里插入图片描述

2、线程和进程

线程、进程,如果不能使用一句话说出来的技术,不扎实!

进程:一个程序,QQ.exe Music.exe 程序的集合;
一个进程往往可以包含多个线程,至少包含一个!
Java默认有几个线程? 2 个 mian、GC
线程:开了一个进程 Typora,写字,自动保存(线程负责的)
对于Java而言:Thread、Runnable、Callable
Java 真的可以开启线程吗? 开不了

并发、并行

并发编程:并发、并行
并发(多线程操作同一个资源)

  • CPU 一核 ,模拟出来多条线程,天下武功,唯快不破,快速交替
    并行(多个人一起行走)
  • CPU 多核 ,多个线程可以同时执行; 线程池

并发编程的本质:充分利用CPU的资源

线程有几个状态

public enum State {// 创建NEW,// 运行RUNNABLE,// 阻塞BLOCKED,// 等待,死死地等WAITING,// 超时等待TIMED_WAITING,// 终止TERMINATED;
}

wait/sleep 区别

1、来自不同的类
wait => Object
sleep => Thread
2、关于锁的释放
wait 会释放锁,sleep 睡觉了,抱着锁睡觉,不会释放!
3、使用的范围是不同的
wait:必须在同步代码块中
sleep 可以再任何地方睡
4、是否需要捕获异常
wait 不需要捕获异常
sleep 必须要捕获异常

3、Lock锁(重点)

传统 Synchronized

package com.kuang.demo01;
// 基本的卖票例子
import java.time.OffsetDateTime;
Lock 接口
/**
* 真正的多线程开发,公司中的开发,降低耦合性
* 线程就是一个单独的资源类,没有任何附属的操作!
* 1、 属性、方法
*/
public class SaleTicketDemo01 {public static void main(String[] args) {// 并发:多线程操作同一个资源类, 把资源类丢入线程Ticket ticket = new Ticket();// @FunctionalInterface 函数式接口,jdk1.8 lambda表达式 (参数)->{ 代码 }new Thread(()->{for (int i = 1; i < 40 ; i++) {ticket.sale();}},"A").start();new Thread(()->{for (int i = 1; i < 40 ; i++) {ticket.sale();}},"B").start();new Thread(()->{for (int i = 1; i < 40 ; i++) {ticket.sale();}},"C").start();}
}
// 资源类 OOPclass Ticket {// 属性、方法private int number = 30;// 卖票的方式// synchronized 本质: 队列,锁public synchronized void sale(){if (number>0){{System.out.println(Thread.currentThread().getName()+"卖出了"+(number--)+"票,剩余:"+number);}}
}

Lock 接口

在这里插入图片描述

可以在ReentrantLock中设置公平和非公平锁

在这里插入图片描述

公平锁:十分公平:可以先来后到
非公平锁:十分不公平:可以插队 (默认)

Lock三部曲

1. new ReentrantLock();
2. lock.lock(); // 加锁
3. finally=> lock.unlock(); // 解锁

在这里插入图片描述

在这里插入图片描述

测试效果一样

Synchronized 和 Lock 区别

1.Synchronized 内置的Java关键字Lock 是一个Java类
2.Synchronized 无法判断获取锁的状态Lock 可以判断是否获取到了锁
3.Synchronized 会自动释放锁lock 必须要手动释放锁!如果不释放锁,死锁
4.Synchronized 线程 1(获得锁,阻塞)、线程2(等待,傻傻的等);Lock锁就不一定会等待下 去
5.Synchronized 可重入锁不可以中断的非公平Lock可重入锁,可以 判断锁非公平(可以 自己设置)
6.Synchronized 适合锁少量的代码同步问题Lock 适合锁大量的同步代码

4、生产者和消费者问题

1)Synchronzied 版本

面试的:单例模式、排序算法、生产者和消费者、死锁

防止虚假唤醒要用while,不能用if

在这里插入图片描述

在这里插入图片描述

package com.marchsoft.juctest;public class ConsumeAndProduct {public static void main(String[] args) {Data data = new Data();new Thread(() -> {for (int i = 0; i < 10; i++) {try {data.increment();} catch (InterruptedException e) {e.printStackTrace();}}}, "A").start();new Thread(() -> {for (int i = 0; i < 10; i++) {try {data.decrement();} catch (InterruptedException e) {e.printStackTrace();}}}, "B").start();}
}class Data {private int num = 0;// +1public synchronized void increment() throws InterruptedException {// 判断等待if (num != 0) {this.wait();}num++;System.out.println(Thread.currentThread().getName() + "=>" + num);// 通知其他线程 +1 执行完毕this.notifyAll();}// -1public synchronized void decrement() throws InterruptedException {// 判断等待if (num == 0) {this.wait();}num--;System.out.println(Thread.currentThread().getName() + "=>" + num);// 通知其他线程 -1 执行完毕this.notifyAll();}
}

效果:
在这里插入图片描述

2)存在问题(虚假唤醒)

问题,如果有四个线程,会出现虚假唤醒

在这里插入图片描述

理解文档

在这里插入图片描述

重点理解if和while的线程唤醒问题

解决方式 ,if 改为while即可,防止虚假唤醒

结论:就是用if判断的话,唤醒后线程会从wait之后的代码开始运行,但是不会重新判断if条件,直接继续运行if代码块之后的代码,而如果使用while的话,也会从wait之后的代码运行,但是唤醒后会重新判断循环条件如果不成立再执行while代码块之后的代码块,成立的话继续wait

这也就是为什么用while而不用if的原因了,因为线程被唤醒后,执行开始的地方是wait之后

​ 拿两个加法线程A、B来说,比如A先执行,执行时调用了wait方法,那它会等待,此时会释放锁,那么线程B获得锁并且也会执行wait方法,两个加线程一起等待被唤醒。此时减线程中的某一个线程执行完毕并且唤醒了这俩加线程,那么这俩加线程不会一起执行,其中A获取了锁并且加1,执行完毕之后B再执行。如果是if的话,那么A修改完num后,B不会再去判断num的值,直接会给num+1。如果是while的话,A执行完之后,B还会去判断num的值,因此就不会执行。

在这里插入图片描述

3)JUC版

在这里插入图片描述

package com.marchsoft.juctest;import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;public class LockCAP {public static void main(String[] args) {Data2 data = new Data2();new Thread(() -> {for (int i = 0; i < 10; i++) {try {data.increment();} catch (InterruptedException e) {e.printStackTrace();}}}, "A").start();new Thread(() -> {for (int i = 0; i < 10; i++) {try {data.decrement();} catch (InterruptedException e) {e.printStackTrace();}}}, "B").start();new Thread(() -> {for (int i = 0; i < 10; i++) {try {data.increment();} catch (InterruptedException e) {e.printStackTrace();}}}, "C").start();new Thread(() -> {for (int i = 0; i < 10; i++) {try {data.decrement();} catch (InterruptedException e) {e.printStackTrace();}}}, "D").start();}
}class Data2 {private int num = 0;Lock lock = new ReentrantLock();Condition condition = lock.newCondition();// +1public  void increment() throws InterruptedException {lock.lock();try {// 判断等待while (num != 0) {condition.await();}num++;System.out.println(Thread.currentThread().getName() + "=>" + num);// 通知其他线程 +1 执行完毕condition.signalAll();}finally {lock.unlock();}}// -1public  void decrement() throws InterruptedException {lock.lock();try {// 判断等待while (num == 0) {condition.await();}num--;System.out.println(Thread.currentThread().getName() + "=>" + num);// 通知其他线程 +1 执行完毕condition.signalAll();}finally {lock.unlock();}}
}
随机执行

在这里插入图片描述

Condition的优势

精准的通知和唤醒的线程!

如何指定线程执行的顺序? 我们可以使用Condition来指定通知进程~

package com.marchsoft.juctest;import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;public class ConditionDemo {public static void main(String[] args) {Data3 data3 = new Data3();new Thread(() -> {for (int i = 0; i < 10; i++) {data3.printA();}},"A").start();new Thread(() -> {for (int i = 0; i < 10; i++) {data3.printB();}},"B").start();new Thread(() -> {for (int i = 0; i < 10; i++) {data3.printC();}},"C").start();}}
class Data3 {private Lock lock = new ReentrantLock();private Condition condition1 = lock.newCondition();private Condition condition2 = lock.newCondition();private Condition condition3 = lock.newCondition();private int num = 1; // 1A 2B 3Cpublic void printA() {lock.lock();try {// 业务代码 判断 -> 执行 -> 通知while (num != 1) {condition1.await();}System.out.println(Thread.currentThread().getName() + "==> AAAA" );num = 2;condition2.signal();}catch (Exception e) {e.printStackTrace();}finally {lock.unlock();}}public void printB() {lock.lock();try {// 业务代码 判断 -> 执行 -> 通知while (num != 2) {condition2.await();}System.out.println(Thread.currentThread().getName() + "==> BBBB" );num = 3;condition3.signal();}catch (Exception e) {e.printStackTrace();}finally {lock.unlock();}}public void printC() {lock.lock();try {// 业务代码 判断 -> 执行 -> 通知while (num != 3) {condition3.await();}System.out.println(Thread.currentThread().getName() + "==> CCCC" );num = 1;condition1.signal();}catch (Exception e) {e.printStackTrace();}finally {lock.unlock();}}
}

测试效果:
在这里插入图片描述

JUC并发编程-线程和进程、Synchronized 和 Lock、生产者和消费者问题 的学习笔记到此完结,笔者归纳、创作不易,大佬们给个3连再起飞吧

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

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

相关文章

创建SERVLET

创建SERVLET 要创建servlet,需要执行以下任务: 编写servlet。编译并封装servlet。将servlet部署为Java EE应用程序。通过浏览器访问servlet。编写servlet 要编写servlet,需要扩展HttpServlet接口的类。编写servlet是,需要合并读取客户机请求和返回响应的功能。 读取和处…

Qt 状态机框架:The State Machine Framework (二)

传送门: Qt 状态机框架:The State Machine Framework (一) Qt 状态机框架:The State Machine Framework (二) 1、利用并行态避免态的组合爆炸 假设您想在单个状态机中对汽车的一组互斥属性进行建模。假设我们感兴趣的属性是干净与肮脏,以及移动与不移动。需要四个相互排斥的…

去掉element-ui的el-table的所有边框+表头+背景颜色

实例: 1.去掉table表头(加上:show-header"false") <el-table:data"tableData":show-header"false"style"width: 100%"> </el-table> 2.去掉table所有边框 ::v-deep .el-table--border th.el-table__cell, ::v-deep .el…

【人工智能平台】ubuntu22.04.3部署cube-studio

简介&#xff1a;本次安装是在虚拟机上进行&#xff0c;需要给虚拟机至少分配16GB&#xff0c;分配8GB时系统会卡死。 一、环境&#xff1a; 主机环境&#xff1a;win11&#xff08;全程科学&#xff09;vm虚拟机 虚拟机&#xff1a;ubuntu22.04.3桌面版&#xff08;新装&…

什么是OSPF?为什么需要OSPF?OSPF基础概念

什么是OSPF&#xff1f; 开放式最短路径优先OSPF&#xff08;Open Shortest Path First&#xff09;是IETF组织开发的一个基于链路状态的内部网关协议&#xff08;Interior Gateway Protocol&#xff09;。 目前针对IPv4协议使用的是OSPF Version 2&#xff08;RFC2328&#x…

多维时序 | Matlab实现CNN-BiLSTM-Mutilhead-Attention卷积双向长短期记忆神经网络融合多头注意力机制多变量时间序列预测

多维时序 | Matlab实现CNN-BiLSTM-Mutilhead-Attention卷积双向长短期记忆神经网络融合多头注意力机制多变量时间序列预测 目录 多维时序 | Matlab实现CNN-BiLSTM-Mutilhead-Attention卷积双向长短期记忆神经网络融合多头注意力机制多变量时间序列预测效果一览基本介绍程序设计…

layui文本编译器支持多图上传,图片上传排序,删除图片功能

layui编译器支持多图上传&#xff0c;图片上传排序&#xff0c;删除图片功能 效果图如下&#xff1a; <div class"layui-tab-item"><textarea id"content" class"js-ueditor" name"content"></textarea> </di…

Django使用session管理购物车

购物车允许用户选择产品并设置他们想要订购的数量&#xff0c;然后在他们浏览网站时临时存储这些信息&#xff0c;直到最终下订单。购物车必须在会话中持久化&#xff0c;以便在用户访问期间维护购物车项目。 使用Django的session框架来持久化购物车。购物车将保持在session中&…

微软使其AI驱动的阅读导师免费

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

Flutter GetX 之 国际化

今天给大家介绍一下 GetX 的国际化功能,在日常开发过程中,我们经常会使用到国际化功能,需要们的应用支持 国际化,例如我们需要支持 简体、繁体、英文等等。 上几篇文章介绍了GetX的 路由管理 和 状态管理,看到大家的点赞和收藏,还是很开心的,说明这两篇文章给大家起到了…

基于Django的Python应用—学习笔记—功能完善

一、让用户可以输入信息 创建forms.py 创建基于表单的页面的方法几乎与前面创建网页一样&#xff1a;定义一个 URL &#xff0c;编写一个视图函数并编写一个模板。一个主要差别是&#xff0c;需要导入包含表单 的模块forms.py 。 from django import forms from .models impor…

Facebook的区块链之路:探秘数字货币的未来

近年来&#xff0c;Facebook一直在积极探索区块链技术&#xff0c;并逐渐将目光聚焦在数字货币领域。从推出Libra项目到改名为Diem&#xff0c;Facebook一直在寻求在数字货币领域取得突破性进展。本文将深入探讨Facebook的区块链之路&#xff0c;揭示其对数字货币未来发展的影响…

Red Hat Enterprise Linux 8.9 安装图解

引导和开始安装 选择倒计时结束前&#xff0c;通过键盘上下键选择下图框选项&#xff0c;启动图形化安装过程。需要注意的不同主板默认或者自行配置的固件类型不一致&#xff0c;引导界面有所不同。也就是说使用UEFI和BIOS的安装引导界面是不同的&#xff0c;如图所示。若手动调…

链表存数相加算法(leetcode第2题)

题目描述&#xff1a; 给你两个 非空 的链表&#xff0c;表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的&#xff0c;并且每个节点只能存储 一位 数字。请你将两个数相加&#xff0c;并以相同形式返回一个表示和的链表。你可以假设除了数字 0 之外&#xff0c;这…

ZVB4/ZVB8罗德与施瓦茨ZVB8网络分析仪8GHz

德国罗德与施瓦茨ZVB8网络分析仪8GHz R&S ZVB8 网络分析仪通过两个或四个测试端口提供高达 8 GHz 的高测量速度。ZVB8 结合了出色的性能、轻巧的设计和紧凑的设计。智能和用户友好的功能提供了最大的操作便利性。R&S ZVB8 网络分析仪可以轻松处理涉及多端口和平衡测量的…

2.C语言——控制语句

控制语句 1.分支语句/判断语句if 语句if...else 语句if...else if...else语句 switch语句 2.循环语句 while 语句 do...while 语句 for 语句 3.转向语句 break continue go to 1.分支语句/判断语句 if 语句 if(boolean_expression) { /* 如果布尔表达式为真将执行的语句 */ } …

UI开发布局-HarmonyOS应用UI开发布局

UI页面的构建不用再像Android开发过程中在.xml文件中书写&#xff0c;可直接在页面上使用声明式UI的方式按照布局进行排列&#xff0c;构建应用的页面。 如下代码使用Row、Column构建一个页面布局&#xff0c;在页面布局中添加组件Text、Button&#xff0c;共同构成页面&#…

C#使用DateTime.Now静态属性动态获得系统当前日期和时间

目录 一、实例 1.源码 2.生成效果 二、相关知识点 1.Thread类 &#xff08;1&#xff09;Thread.Sleep()方法 &#xff08;2&#xff09;Thread(ThreadStart) &#xff08;3&#xff09;IsBackground &#xff08;4&#xff09;Invoke( &#xff09; 2.CreateGrap…

前端打同一个包可以从测试晋升到生产的配置方案

前端打同一个包从测试晋升到生产环境的方案&#xff0c;是一种高效、可靠且易于维护的部署方式。在这种方案中&#xff0c;前端代码在开发完成后&#xff0c;经过测试验证无误后&#xff0c;可以直接打包部署到生产环境&#xff0c;无需进行额外的配置或修改。这样可以减少部署…

面试题:40亿个QQ号,限制1G内存,如何去重?

文章目录 概要什么是BitMap&#xff1f;有什么用&#xff1f;什么是布隆过滤器&#xff0c;实现原理是什么&#xff1f;应用场景如何使用 概要 40亿个unsigned int&#xff0c;如果直接用内存存储的话&#xff0c;需要&#xff1a; 4*4000000000 /1024/1024/1024 14.9G &…