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

news2024/12/25 9:08:27

线程与进程

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();//ready
        t1.start();//就绪,CPU有时间片才会运行,也不是一定运行。
    }

    @Override
    public 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;
    }

    @Override
    public 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
            @Override
            public 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() {
         @Override
         public 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() {
         @Override
         public 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: true
        Thread t1 = new Thread(() -> {
            while (true) {
                if (flag) {
                    System.out.println("A:" + flag);
                }
            }
        });

        //100ms之后将flag变为true
        Thread 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;
    }

    @Override
    public 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;
    }

    @Override
    public 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;
    }

    @Override
    public 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

在这里插入图片描述

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

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

相关文章

ubuntu 设置静态IP

一、 ip addresssudo nano /etc/netplan/50-cloud-init.yaml 修改前&#xff1a; 修改后&#xff1a; # This file is generated from information provided by the datasource. Changes # to it will not persist across an instance reboot. To disable cloud-inits # ne…

深度解析与解决方案:U盘有盘符但无法打开的困境

引言&#xff1a;U盘困境初现 在日常工作与生活中&#xff0c;U盘作为便携式存储设备&#xff0c;扮演着数据传输与备份的重要角色。然而&#xff0c;不少用户会遇到这样一个棘手问题&#xff1a;U盘在插入电脑后能够正常显示盘符&#xff0c;但尝试打开时却遭遇拒绝访问或提示…

巧用时间换空间:解读 ArcGraph 如何灵活应对有限内存下的图分析

导读&#xff1a;ArcGraph 是一款云原生架构、存查分析一体化的分布式图数据库。本文将详细解读 ArcGraph 如何灵活应对有限内存下的图分析。 01 引言 在图分析技术广泛应用的当下&#xff0c;学术界和各大图数据库厂商热衷于提升图分析技术的高性能指标。然而&#xff0c;追求…

STM32嵌入式编程学习到提高:【5】delay函数

------------------------------------------------------------------------------------------------------------------------- 工程文件&#xff1a;放在百度云盘里&#xff0c;需要的自行下载&#xff01;&#xff01;&#xff01; 链接:http:// https://pan.baidu.com/s…

【3D分割】Segment Anything in 3D with Radiance Fields

论文链接&#xff1a;Segment Anything in 3D with Radiance Fields 代码链接&#xff1a;GitHub - Jumpat/SegmentAnythingin3D: Segment Anything in 3D with NeRFs (NeurIPS 2023) 作者&#xff1a;Jiazhong Cen, Jiemin Fang, Zanwei Zhou, Chen Yang, Lingxi Xie, Xiaop…

DataLight(V1.4.5) 版本更新,新增 Ranger、Solr

DataLight&#xff08;V1.4.5&#xff09; 版本更新&#xff0c;新增 Ranger、Solr DataLight 迎来了重大的版本更新&#xff0c;现已发布 V1.4.5 版本。本次更新对平台进行了较多的功能拓展和优化&#xff0c;新增了对 Ranger 和 Solr 服务组件的支持&#xff0c;同时对多项已…

微服务的优点及在云原生时代的合理落地方式

云计算de小白 那么&#xff0c;微服务到底能给业务带来什么好处&#xff1f;在云原生时代&#xff0c;如何更合理地实现微服务&#xff1f; 架构没有好坏之分&#xff0c;只有适合与不适合。然而&#xff0c;当我们对比微服务架构与单体架构时&#xff0c;可以发现微服务有以…

【【通信协议之UDP协议】】

通信协议之UDP协议 UDP &#xff08;user Datagram Protocol )用户数据报协议 整个的UDP数据格式 如下所示 TCP协议与UDP协议的区别 TCP协议面向连接&#xff0c;是流传输协议&#xff0c;通过连接发送数据&#xff0c;而 UDP 协议传输不需要连接&#xff0c;是数据包协议 …

[3]Opengl ES着色器

术语&#xff1a; VertexShader&#xff1a;顶点着色器&#xff0c;用来描述图形图像位置的顶点坐标&#xff1b; FragmentShader&#xff1a;片元着色器&#xff0c;用来给顶点指定的区域进行着色&#xff1b; Vertex&#xff1a;顶点 Texture&#xff1a;纹理…

【中级通信工程师】终端与业务(十一):市场营销计划、实施与控制

【零基础3天通关中级通信工程师】 终端与业务(十一)&#xff1a;市场营销计划、实施与控制 本文是中级通信工程师考试《终端与业务》科目第十一章《市场营销计划、实施与控制》的复习资料和真题汇总。本章的核心内容涵盖了市场营销计划的编制、实施过程以及控制方式&#xff0…

【Java异常】(简简单单拿捏)

【Java异常】&#xff08;简简单单拿捏&#xff09; 1. 异常的简单介绍2. 异常的抛出2.1 语法 3. 异常的处理3.1 异常声明throws3.2 try-catch捕获并处理 4. 例子&#xff08;try-catch自定义异常&#xff09; 1. 异常的简单介绍 程序员在运行代码时会遇到很多异常&#xff0c…

Python :AVIF 图片与其他图片格式间的批量转换

图片格式 AVIF转换为常见的格式&#xff0c;比如 JPG 或 PNG。本文介绍如何使用 Pillow 库实现AVIF与其他格式的相互转换。 环境配置 使用 Python 环境管理工具 conda 和常用库 Pillow 来处理图片格式转换。环境的详细信息&#xff1a; Conda: 24.7.1Python: 3.8.19Pillow: 10…

【HTML|第1期】HTML5视频(Video)元素详解:从起源到应用

日期&#xff1a;2024年9月9日 作者&#xff1a;Commas 签名&#xff1a;(ง •_•)ง 积跬步以致千里,积小流以成江海…… 注释&#xff1a;如果您觉在这里插入代码片得有所帮助&#xff0c;帮忙点个赞&#xff0c;也可以关注我&#xff0c;我们一起成长&#xff1b;如果有不对…

plt绘图日常训练

目录 练习1练习2练习3练习4练习5 前几节课已经介绍plt常用的函数&#xff0c;这节课主要是一些练习&#xff0c;方便大家熟悉 练习1 主要学习plt.figure()及plt的基本操作 import matplotlib.pyplot as plt import numpy as npxnp.linspace(-3,3,50) y1 2*x1 y2x**2plt.figur…

Windows下安装 LLama-Factory 保姆级教程

本机配置 品牌&#xff1a;联想拯救者Y9000x-2022CPU&#xff1a;12th Gen Intel Core™ i7-12700H 2.30 GHzRAM&#xff1a;24.0 GB (23.8 GB 可用)GPU&#xff1a; NVIDIA GeForce RTX 3060 Laptop GPU 6GCUDA版本&#xff1a;12.3 (可以在PowerShell下输入 nvidia-smi 命令…

短剧向左,体育向右,快手前途未卜?

最近&#xff0c;辗转于多项业务的快手收到了来自于市场“寓褒于贬”的评价。 麦格理发表报告表示&#xff0c;短剧业务正成为快手近期新的增长动力&#xff0c;亦维持对快手的正面看法&#xff0c;给予“跑赢大市”评级&#xff0c;预期上市前投资者出售2%股份对基本面没有太…

深入理解 `torch.nn.Linear`:维度变换的过程详解与实践(附图、公式、代码)

在深度学习中&#xff0c;线性变换是最基础的操作之一。PyTorch 提供了 torch.nn.Linear 模块&#xff0c;用来实现全连接层&#xff08;Fully Connected Layer&#xff09;。在使用时&#xff0c;理解维度如何从输入映射到输出&#xff0c;并掌握其具体的变换过程&#xff0c;…

更改远程访问端口

1、背景 在客户现场&#xff0c;由于安全限制&#xff0c;在内网的交换机中配置的某些限制&#xff0c;不允许使用22端口作为远程访问服务器的端口&#xff0c;此时就需要更改远程访问的端口。 2、前提 在修改默认的远程访问端口22时&#xff0c;可以需要在Linux服务器中支持…

三.python入门语法1

目录 1. 算数运算和关系运算 1.1. 算术运算符 1.2. 关系运算符 习题 2.赋值运算和逻辑运算 2.1. 赋值运算符 2.2. 逻辑运算符 3.位运算符 1&#xff09;位与运算&#xff08;A&B&#xff09; 2&#xff09;位或运算&#xff08;A|B&#xff09; 3&#xff09;异或位…

uni-app运行到 Android 真机和Android studio模拟器

文章目录 1、运行到Android 真机2、运行到Android studio模拟器2.1、运行到Android studio模拟器Android studio的安装步骤2.2、安装android SDK2.3、新增虚拟设备2.4、项目运行 3、安装报错3.1、安卓真机调试提示检测不到手机【解决办法】3.2、Android Studio中缺少System Ima…