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

线程与线程安全,生产消费者模型

线程与进程

2390. 从字符串中移除星号

给你一个包含若干星号 * 的字符串 s

在一步操作中,你可以:

  • 选中 s 中的一个星号。
  • 移除星号 左侧 最近的那个 非星号 字符,并移除该星号自身。

返回移除 所有 星号之后的字符串**。**

注意:

  • 生成的输入保证总是可以执行题面中描述的操作。
  • 可以证明结果字符串是唯一的。

示例 1:

输入:s = "leet**cod*e"
输出:"lecoe"
解释:从左到右执行移除操作:
- 距离第 1 个星号最近的字符是 "leet**cod*e" 中的 't' ,s 变为 "lee*cod*e"- 距离第 2 个星号最近的字符是 "lee*cod*e" 中的 'e' ,s 变为 "lecod*e"- 距离第 3 个星号最近的字符是 "lecod*e" 中的 'd' ,s 变为 "lecoe" 。
不存在其他星号,返回 "lecoe"

StringBuilder内置加,删。

  • 复习

在这里插入图片描述

  • 方案一:先放进去在扫描
  • 在这里插入图片描述

在这里插入图片描述

  • 方案二:一个个放,遇到*删除and弹出栈顶。
  • 在这里插入图片描述
  • 方案三:放到Stringbuilder
  • 在这里插入图片描述
  • 在这里插入图片描述

引入

在这里插入图片描述

  • cpu主要用于寻址。
  • 摩尔定律

是由英特尔(Intel)创始人之一戈登·摩尔(Gordon Moore)提出来的。其内容为:当价格不变时,集成电路上可容纳的元器件的数目,约每隔18-24个月便会增加一倍,性能也将提升一倍。换言之,每一美元所能买到的电脑性能,将每隔18-24个月翻一倍以上。这一定律揭示了信息技术进步的速度。 尽管这种趋势已经持续了超过半个世纪,摩尔定律仍应该被认为是观测或推测,而不是一个物理或自然法。预计定律将持续到至少2015年或2020年。然而,2010年国际半导体技术发展路线图的更新增长已经放缓在2013年年底,之后的时间里晶体管数量密度预计只会每三年翻一番。

在这里插入图片描述

进程是任务,线程是分配任务。

进程

在这里插入图片描述

并发与并行:

在这里插入图片描述

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

多线程的缺点:管理不便。

在这里插入图片描述

new,start(创建,就绪),运行,堵塞,自然死亡。

package com.ffyc.thread;/*** 写10个1~10* 分任务!* @param args*/public class ThreadDemo02 extends Thread{public static void main(String[] args) {Thread t1 = new ThreadDemo02();Thread t2 = new ThreadDemo02();t2.start();//readyt1.start();//就绪,CPU有时间片才会运行,也不是一定运行。}@Overridepublic void run() {for (int i = 1; i <=10 ; i++) {System.out.print(i+"\t");}System.out.println();}
}

在这里插入图片描述

线程生命周期

在这里插入图片描述

*核心

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

package com.ffyc.thread;/*** Runnable接口实现(可以继承)* why:java单继承、多实现*/
public class ThreadDemo03 implements Runnable{private String name;public ThreadDemo03(String name) {this.name = name;}@Overridepublic void run() {for (int i = 0; i < 10; i++) {System.out.println(this.name+"-->"+i);}}public static void main(String[] args) {Thread t1 = new Thread(new ThreadDemo03("A"));Thread t2 = new Thread(new ThreadDemo03("B"));t2.start();t1.start();}
}

在这里插入图片描述

Runnable

在这里插入图片描述

  • 对比函数式接口 VS 匿名内部类(接口在内部实现)

  • 在这里插入图片描述

  • 点灰色–>lambda表示式

  • 在这里插入图片描述

  • lambda表示式

  • List排顺序Camparator o1 - o2;逆序 o2- o1。

  • 在这里插入图片描述

  • 二维数组排序

  • 在这里插入图片描述

package com.ffyc.thread;import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;public class SortDemo {public static void main(String[] args) {List<Integer> list = new ArrayList<>();//动态数组list.add(1);list.add(3);list.add(2);System.out.println(list);//无序:1 3 2 //自己写排序【empty】// OR jdk排list.sort(new A());//写一个A排序System.out.println("Sort:"+list);list.sort(new Comparator<Integer>() {//lambda@Overridepublic int compare(Integer f, Integer l) {return f-l;}});System.out.println("first-last:"+list);}
}
package com.ffyc.thread;public class ThreadDemo05 {public static void main(String[] args) {/*** Runnable匿名内部类*/Thread t1 = new Thread(new Thread(() -> {for (int i=1;i<10;i++){System.out.println("A->"+i);}}));Thread t2 = new Thread(new Thread(() -> {for (int i=1;i<20;i++){System.out.println("B->"+i);}}));t1.start();t2.start();}
}

block():阻塞

三种解决方法:

  1. sleep()–>唤醒前要就绪
  2. yield
  3. join
  4. wait——高级别–》对all对象

在这里插入图片描述

可怕

在这里插入图片描述

List扩容时可能加入新的元素,不安全。

  • 在这里插入图片描述

守护线程和用户线程

守护最后一个用户线程结束才结束。

守护线程–> .setDaemon(true)
package com.ffyc.thread;import java.text.SimpleDateFormat;
import java.util.Date;/*** 守护线程*/
public class ProtectThread {public static void main(String[] args) {Thread t1 = new Thread(()->{while (true){try {Date d = new Date();SimpleDateFormat sdf = new SimpleDateFormat("yy-MM-dd hh:mm:ss");System.out.println(sdf.format(d));Thread.sleep(100);} catch (InterruptedException e) {throw new RuntimeException(e);}}});Thread t2 = new Thread(()->{for (int i = 0; i < 100; i++) {try {System.out.println("我是00"+i);Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}});t1.setDaemon(true);t1.start();t2.start();}}

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

用户线程

复习:

  1. 线程
  2. 集合
  3. 面向对象

线程安全

回顾生命周期

在这里插入图片描述

三大特性

  1. 原子性(理论上)——线程任务不可再分。
  2. 可见性——线程之间的操作互相不可见。
  3. 有序性——程序运行顺序不能改变。

特性一:原子性 代码举例

int i = 1;
i++;

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

原子类–多线程时±/*安全。

AtomicXXX

package com.ffyc.Thread;import java.util.concurrent.atomic.AtomicInteger;/*** 特性一:原子性* i++/++i ===> 不安全---why:两步完成。
*/
public class ThreadDemo01 {//static int x = 1;static AtomicInteger a = new AtomicInteger(1);public static void main(String[] args) {Thread t1 = new Thread(new Runnable() {@Overridepublic void run() {for (int i = 0; i < 100; i++) {System.out.println(a.addAndGet(1));try {Thread.sleep(100);} catch (InterruptedException e) {throw new RuntimeException(e);}}}});Thread t2 = new Thread(new Runnable() {@Overridepublic void run() {try {for (int i = 0; i < 100; i++) {System.out.println(a.addAndGet(1));Thread.sleep(100);}} catch (InterruptedException e) {throw new RuntimeException(e);}}});// 启动线程t1.start();t2.start();}
}

在这里插入图片描述

特性二:互盲

在这里插入图片描述
但不能保证有序。

Eg:

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

升级

在这里插入图片描述

package com.ffyc.thread;public class ThreadDemo02 {static volatile boolean flag = false;public static void main(String[] args) {//线程A如果,flag为true,就运行打印语句 A: trueThread t1 = new Thread(() -> {while (true) {if (flag) {System.out.println("A:" + flag);}}});//100ms之后将flag变为trueThread t2 = new Thread(() -> {try {Thread.sleep(100);flag = true;System.out.println("B:" + flag);} catch (InterruptedException e) {throw new RuntimeException(e);}});t1.start();t2.start();}
}

特性三:不能改变固有顺序

在这里插入图片描述

“重点”解决线程安全方案——*锁🔒

原理

  1. 每一个对象只有一把锁,
  2. 每个线程抢锁,先拿到的线程就是锁的持有者。
  3. 持有锁的线程访问有synchronized标记的方法/代码块
  4. 离开synchronized,线程releas(释放)锁🔒

现实场景:买票程序

在这里插入图片描述

在这里插入图片描述

ticket
package com.ffyc.ticket;public class Ticket {private Integer num;private String name;public Ticket(Integer num) {this.num = num;}public Ticket(Integer num, String name) {this.num = num;this.name = name;}/*** 取出剩余票数* @return*/public Integer getNum() {return num;}/*** 卖票* @param name* //sy 同步 解决*/public synchronized void sold(String name){System.out.println("站点"+name+"购买成功,余票"+ (--num)+"票");//why前减}
}
tivketThread
package com.ffyc.ticket;public class TicketsThread extends Thread{private final String name;private final Ticket ticket;public TicketsThread(Ticket ticket,String name){this.ticket=ticket;this.name = name;}@Overridepublic void run(){// synchronized (ticket.getNum()){//解决-1,-2票的打印问题,但是全是A买的。while (ticket.getNum()>2){//笨办法解决try {sleep(100);ticket.sold(name);} catch (InterruptedException e) {throw new RuntimeException(e);}}}//}}
TicketTest
package com.ffyc.ticket;public class TestTicket {public static void main(String[] args) {Ticket ticket = new Ticket(100);Thread a = new TicketsThread(ticket, "A");Thread b= new TicketsThread(ticket,"B");Thread c = new TicketsThread(ticket,"C");a.start();c.start();b.start();}
}

在这里插入图片描述

Ways:

  1. 方法体
  2. 方法里**{代码块},注意不能有基本数据类型,要用包装类型。**
改造Atomic
sy联系:StringBuffer,Vector。

在这里插入图片描述

Asy异步 ——》 前端里用

持有锁

在这里插入图片描述

死锁

sy(A){

​ sy(B){ }

}

在这里插入图片描述

Resource
package com.ffyc.lock;public class Resource {private String name;public Resource(String name) {this.name= name;}public String getName() {return name;}@Overridepublic String toString() {return "Resource{" +"name='" + name + '\'' +'}';}
}
DeadLockThread
package com.ffyc.lock;public class DeadLockThread extends Thread{private Resource x;private Resource y;public  DeadLockThread(Resource x, Resource y) {this.x = x;this.y = y;}@Overridepublic void run() {synchronized (x){System.out.println(x.getName()+"锁定"+x.getName()+"成功...");try {sleep(200);System.out.println(x.getName()+"准备--->锁定"+y.getName()+">>>>");synchronized (y){System.out.println(x.getName()+"锁定"+y.getName()+"成功...");}System.out.println("释放"+y.getName()+"成功...");} catch (InterruptedException e) {throw new RuntimeException(e);}}System.out.println("释放"+x.getName()+"成功...");}}
Main
package com.ffyc.lock;public class Main {public static void main(String[] args) {Resource lwh = new Resource("李文豪");Resource wzy = new Resource("隗子垚");Resource fzy = new Resource("冯正阳");Thread a = new DeadLockThread(lwh, fzy);Thread b = new DeadLockThread(fzy, wzy);Thread c = new DeadLockThread(wzy, lwh);a.start();b.start();c.start();}}

在这里插入图片描述

leetcode191

        int num = 0;String s = Integer.toBinaryString(n);for (int i = 0; i < s.length(); i++) {if (s.charAt(i)=='1') num++;}return num;

在这里插入图片描述

生产者消费者模型

在这里插入图片描述

hamburger类

在这里插入图片描述

HLS

在这里插入图片描述

在这里插入图片描述

用wait记得抛线程异常。

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

消费者consumer

在这里插入图片描述

Main

在这里插入图片描述

ProducerThread生产者线程

在这里插入图片描述

ConsumerThread

在这里插入图片描述

相关文章:

  • Python+appium自动化+夜神模拟器inspector部署验证
  • 【工具类】证书自动续签免费版 正式发布
  • fiddler抓包07_抓IOS手机请求
  • Pinia从安装到使用
  • Metasploit渗透测试之服务端漏洞利用
  • 在vue2项目中使用dart-sass
  • 【JavaEE】——内存可见性问题
  • 基于keras 的神经网络股价预测模型
  • 基于springboot+vue医院挂号就诊系统设计与实现
  • C#和数据库高级:虚方法
  • android 页面布局(1)
  • 章管家 listUploadIntelligent.htm SQL注入漏洞
  • matlab r2024a、matlab R2024b保姆级安装教程
  • 语音识别(非实时)
  • Python编程:08- pycharm使用技巧
  • 【跃迁之路】【733天】程序员高效学习方法论探索系列(实验阶段490-2019.2.23)...
  • Angular 响应式表单之下拉框
  • Promise面试题,控制异步流程
  • Python利用正则抓取网页内容保存到本地
  • React Native移动开发实战-3-实现页面间的数据传递
  • Redis的resp协议
  • 编写高质量JavaScript代码之并发
  • 基于遗传算法的优化问题求解
  • 什么软件可以提取视频中的音频制作成手机铃声
  • -- 数据结构 顺序表 --Java
  • 消息队列系列二(IOT中消息队列的应用)
  • 源码安装memcached和php memcache扩展
  • 自定义函数
  • 06-01 点餐小程序前台界面搭建
  • Semaphore
  • 好程序员大数据教程Hadoop全分布安装(非HA)
  • ​Linux·i2c驱动架构​
  • # Swust 12th acm 邀请赛# [ A ] A+B problem [题解]
  • #我与Java虚拟机的故事#连载17:我的Java技术水平有了一个本质的提升
  • $HTTP_POST_VARS['']和$_POST['']的区别
  • (2024,LoRA,全量微调,低秩,强正则化,缓解遗忘,多样性)LoRA 学习更少,遗忘更少
  • (poj1.3.2)1791(构造法模拟)
  • (附源码)python旅游推荐系统 毕业设计 250623
  • (附源码)计算机毕业设计ssm基于B_S的汽车售后服务管理系统
  • (蓝桥杯每日一题)平方末尾及补充(常用的字符串函数功能)
  • (四) 虚拟摄像头vivi体验
  • (四)模仿学习-完成后台管理页面查询
  • (四)软件性能测试
  • (原創) X61用戶,小心你的上蓋!! (NB) (ThinkPad) (X61)
  • .bat批处理(三):变量声明、设置、拼接、截取
  • .bat批处理(四):路径相关%cd%和%~dp0的区别
  • .NET CORE Aws S3 使用
  • .NET Core中Emit的使用
  • .NET Core中如何集成RabbitMQ
  • .net mvc 获取url中controller和action
  • .Net Winform开发笔记(一)
  • .net 反编译_.net反编译的相关问题
  • .Net 访问电子邮箱-LumiSoft.Net,好用
  • .net 写了一个支持重试、熔断和超时策略的 HttpClient 实例池
  • .net 验证控件和javaScript的冲突问题