JavaSE学习笔记总结day19

news2024/11/14 12:18:59

今日内容

二、线程安全的集合
三、死锁
四、线程通信
五、生产者消费者
六、线程池

零、 复习昨日

创建线程的几种方式 1) 继承 2) 实现Runnable 3) callable接口 Future接口 4) 线程池
启动线程的方法 start()
线程的几种状态
什么是线程不安全


setName getName
Thread.currentThread()
join
sleep


synchronized

一、作业

售卖后车票

package com.qf.homework;


public class Window implements Runnable {

    // 票(加static,被该类所有对象共享)
    private static int ticket = 100;

    // 售票任务
    @Override
    public void run() {
        while (true) {
            synchronized (Window.class) {
                if (ticket > 0) {
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace( );
                    }
                    System.out.println(Thread.currentThread( ).getName( ) + "有余票,正在售出" + ticket);
                    ticket--;
                } else {
                    System.out.println("票已售完");
                    return;
                }
            }
        }
    }
}
    public static void main(String[] args) {
        new Thread( new Window() ,"窗口1").start();
        new Thread( new Window() ,"窗口2").start();
        new Thread( new Window() ,"窗口3").start();
    }

二、线程安全的集合

StringBuffer是线程安全的,是因为每个方法都加上synchronized,即都是同步方法
StringBuilder没有加

image-20230303094122011

image-20230303094159112

ArrayList是线程不安全
Vector 是线程安全

image-20230303094527278

HashMap 是线程不安全
Hashtable 是线程安全

image-20230303095012216

比HashMap安全,比Hashtable快,即安全又快的集合ConcurrentHashMap[很重要]

三、死锁

死锁: 互相持有对方的锁还不释放

public class MyLock {
    static Object zuo = new Object();
    static Object you = new Object();
}
public class Boy extends Thread{

    @Override
    public void run() {
        synchronized (MyLock.zuo){
            System.out.println("男朋友-拿到左筷子" );
            synchronized (MyLock.you) {
                System.out.println("男朋友-拿到右筷子,开吃" );
            }
        }
    }
}
public class Girl extends Thread{

    @Override
    public void run() {
        synchronized (MyLock.you){
            System.out.println("女朋友-拿到右筷子" );
            synchronized (MyLock.zuo) {
                System.out.println("女朋友-拿到左筷子,开吃" );
            }
        }
    }
}
public class TestDeadLock {
    public static void main(String[] args) {
        new Boy().start();
        new Girl().start();

    }
}

男生先拿到zuo锁,再去获得you锁即可吃饭
但是you锁在女生那里,女生需要获得zuo锁才能吃饭
即 男生需要的you锁被女生拿着,女生需要的zuo锁被男生拿着
互相持有对方的锁,还不释放,就会出现"死锁" 程序卡死,不往下执行,持续阻塞

四、线程通信

线程通信,就是线程之间产生联系.

即通知,例如线程A执行到一定时候会停下,同时通知另外的线程B执行,
线程B执行到一定时候,也停下,通知线程A执行

以上操作需要Object类的方法

  • wait() 让当前线程等待
  • notify() 唤醒一个处于等待状态的线程

特殊的:

  • wait和notify方法需要在同步方法或者同步代码块内执行
  • wait会让当前线程进入等待状态,让出资源,其他线程可以执行

问 wait和sleep有什么区别?

答:

  • wait是Object类的方法,sleep是Thread类方法

  • wait和sleep都可以让当前线程进入阻塞状态

  • 但是wait阻塞当前线程,会让出系统资源,其他线程可执行;但是sleep阻塞当前线程,会持有锁不释放,其他线程无法执行

  • wait需要在同步方法或同步代码快中使用,但是sleep可以在同步或非同步都可以使用

ps: 搞个表格

waitsleep
不同点属于Object类中的方法,需要再同步代码块或同步方法中。属于Thread方法,可以同步或不同步的执行。
相同让线程阻塞,会让出系统资源让线程阻塞,持有锁不释放资源

问 为什么wait和notify方法要设计在Object类中?

答: 因为锁可以是任意对象,有因为wait和notify需要被 锁对象调用,所以锁对象任意,wait和notify方法也能被任意对象调用,所以就设计在Object类中,因为Object类是所有类的父类

需求: 昨天打印机方法,让print1()和print2()方法交替执行

package com.qf.notify;


public class Printer {

    // 具体哪台打印机执行的标志
    private int flag = 1;

    // 现在使用同步方法,print1和print2方法由同一个对象打印机对象调用
    // print1方法和print2方法锁是同一个,是this,即打印机对象
    public synchronized void print1() {
        if (flag != 1) {
            try {
                // 锁是谁,就用谁调用wait
                // 当前线程就陷入等待,会让出资源释放锁
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace( );
            }
        }
        System.out.print("1 ");
        System.out.print("2 ");
        System.out.print("3 ");
        System.out.print("4 ");
        System.out.print("\r\n");

        // 干完活,修改标志
        flag = 2;

        // 通知另外一个处于等待状态的线程
        // 锁是谁,用谁调用方法
        this.notify();
    }


    public synchronized void print2() {
        if (flag != 2) {
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace( );
            }
        }
        System.out.print("A ");
        System.out.print("B ");
        System.out.print("C ");
        System.out.print("D ");
        System.out.print("\r\n");

        flag = 1;
        this.notify();
    }
}
// 测试
public class TestNotify {

    public static void main(String[] args) {

        Printer printer = new Printer( );

        new Thread(){
            @Override
            public void run() {
                while (true){
                    printer.print1();
                }
            }
        }.start();

        new Thread(){
            @Override
            public void run() {
                while (true){
                    printer.print2();
                }
            }
        }.start();
    }
}

换用同步代码块实现

package com.qf.notify;


public class Printer {

    // 锁对象
    private Object obj = new Object();

    // 具体哪台打印机执行的标志
    private int flag = 1;

    // 现在使用同步方法,print1和print2方法由同一个对象打印机对象调用
    // print1方法和print2方法锁是同一个,是this,即打印机对象
    public void print1() {
        // 同步代码块,现在锁是字节码文件
        synchronized(Printer.class) {
            if (flag != 1) {
                try {
                    // 锁是谁,就用谁调用wait
                    // 当前线程就陷入等待,会让出资源释放锁
                    // 用字节码锁来调用wait方法
                    Printer.class.wait( );
                } catch (InterruptedException e) {
                    e.printStackTrace( );
                }
            }
            System.out.print("1 ");
            System.out.print("2 ");
            System.out.print("3 ");
            System.out.print("4 ");
            System.out.print("\r\n");

            // 干完活,修改标志
            flag = 2;

            // 通知另外一个处于等待状态的线程
            // 只能唤醒在此对象监视器(加过锁的)上等待的单个线程.
            // 如果没有加锁,直接调用该方法唤醒线程,会报错IllegalMonitorStateException
            // 锁是谁,用谁调用方法
            Printer.class.notify( );

        }
    }


    public  void print2() {
        synchronized( Printer.class) {
            if (flag != 2) {
                try {
                    Printer.class.wait( );
                } catch (InterruptedException e) {
                    e.printStackTrace( );
                }
            }
            System.out.print("A ");
            System.out.print("B ");
            System.out.print("C ");
            System.out.print("D ");
            System.out.print("\r\n");

            flag = 1;
            Printer.class.notify( );
        }
    }
}
- void start() 开启线程
- void run() 执行线程的方法
	- run() 方法是start开启线程后,JVM自动调用
- void setName(String name) 给线程设置名字
- String getName() 获得线程的名字
- static Thread currentThread() 返回当前正在执行的线程对象
- setPriority(int priority) 设置优先级
  - 级别是1-10 ,默认是5
- getPriority() 获得优先级
- join()  加入线程,等待该线程终止
- join(int milles) 加入线程,最大等待直到毫秒数
- void setDaemon(boolean on) 设置守护线程
- static void yield() 礼让线程,暂停当前线程,让其他线程执行
- static void sleep(long milles) 线程休眠
- void stop() 结束当前线程,线程死亡

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NV4f7qWm-1678065007263)(D:\前锋学习笔记\笔记\image-20230306090803972.png)]

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

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

相关文章

基于intel soc+fpga智能驾驶舱和高级驾驶辅助系统软件设计(三)

虚拟化操作系统介绍 车载平台有逐渐融合的趋势,车载 SoC 的计算性能和应用快速增长,面临着多种应用在 多个显示子系统融合在一起的问题,这就要求平台运行多个操作系统。虚拟化(Virtualization) 技术飞速发展&#xff0…

软件测试培训三个月,找到工作了11K,面试总结分享给大家

功能方面:问的最多的就是测试流程,测试计划包含哪些内容,公司人员配置,有bug开发认为不是 bug怎么处理,怎样才算是好的用例,测试用例设计方法(等价类,边界值等概念方法)&…

ETL的模式以及优缺点

首先,ETL有四种主要实现模式:触发器模式、增量字段、全量同步、日志比对。其次,四种模式的优缺点触发器模式优点:数据抽取的性能高,ETL 加载规则简单,速度快,不需要修改业务系统表结构&#xff…

科目二练习与考试点位总结

一,开车前检查1.调整桌椅。2.调整左右后视镜。3.系安全带。二、倒车入库右边倒车直行至左肩与左虚线重合停车,倒车,左视镜下沿与左虚线重合或10cm左右,方向盘右打满。看右视镜第二个虚线一半回一圈。看右视镜右库角消失右打满。观…

Qt音视频开发20-vlc内核动态保存录像文件(不需要重新编译源码)

一、前言 在vlc默认提供的保存文件方式中,通过打开的时候传入指定的参数来保存文件,直到关闭播放生成文件,这种方式简单暴力,但是不适用大部分的场景,大部分时候需要的是提供开始录制和停止录制的功能,也就…

【springmvc】Rest ful风格

RESTful 1、RESTful简介 REST:Representational State Transfer,表现层资源状态转移。 a>资源 资源是一种看待服务器的方式,即,将服务器看作是由很多离散的资源组成。每个资源是服务器上一个可命名的抽象概念。因为资源是一…

华为OD机试题,用 Java 解【获取最大软件版本号】问题

华为Od必看系列 华为OD机试 全流程解析+经验分享,题型分享,防作弊指南)华为od机试,独家整理 已参加机试人员的实战技巧华为od 2023 | 什么是华为od,od 薪资待遇,od机试题清单华为OD机试真题大全,用 Python 解华为机试题 | 机试宝典使用说明 参加华为od机试,一定要注意不…

如何用MD5和SHA等构造密码方案中的哈希函数

文章目录常见符号如何实现 H:{0,1}∗→Zp∗H : \{0, 1\}^* \to \mathbb{Z}^*_pH:{0,1}∗→Zp∗​如何实现 H:Zp∗→{0,1}λH: \mathbb{Z}^*_p \to \{0, 1\}^\lambdaH:Zp∗​→{0,1}λ如何实现 H:M→ZN∗H: \mathcal{M} \to \mathbb{Z}^*_NH:M→ZN∗​如何实现 H:{0,1}∗→GH: \…

ElasticSearch - ElasticSearch基本概念及集群内部原理

文章目录1. ElasticSearch的应用场景01. Elasticsearch 是什么?02. 为何使用 Elasticsearch?03. Elasticsearch 的用途是什么?04. Elasticsearch 的工作原理是什么?05. Elasticsearch 索引是什么?06. Logstash 的用途是…

SAP UI5 Upload/Download file through NetWeaver Gateway

1、创建 SEGW对象 2、创建Entity Type 要把Media 标识打上 3、 激活对象然后到DPC Class的扩展对象里面重定义 /IWBEP/IF_MGW_APPL_SRV_RUNTIME~GET_STREAM /IWBEP/IF_MGW_APPL_SRV_RUNTIME~CREATE_STREAM /IWBEP/IF_MGW_APPL_SRV_RUNTIME~UPDATE_STREAM METHOD /iwbep/if_m…

手写操作系统+文件系统开源啦

哈喽,我是子牙,一个很卷的硬核男人。喜欢研究底层,聚焦做那些大家想学没地方学的课程:手写操作系统、手写虚拟机、手写模拟器、手写编程语言… 今年是我创业的第二年,已经做了两个课程:手写JVM、手写操作系…

十五、Spring中的八大模式

1 简单工厂模式 BeanFactory的getBean()方法,通过唯一标识来获取Bean对象。是典型的简单工厂模式(静态工厂模式); 2 工厂方法模式 FactoryBean是典型的工厂方法模式。在配置文件中通过factory-method属性来指定工厂方法&#x…

多线程的创建、Thread类、线程安全、同步、通信

目录 多线程的创建 方式一:继承Thread类 方式二:实现Runnable接口 方式三:JDK 5.0新增:实现Callable接口 Thread的常用方法 线程安全 线程安全问题是什么、发生的原因 线程安全问题案例模拟 线程同步 同步思想概述 方式…

0202state详解-组件-React

文章目录1 state简介2 初始化state3 React中事件绑定4 类方法中this指向问题5 解决React类组件方法this指向5 setState5.1 更新state状态数据方式5.2 更新state整体替换还是合并相同项?5.3 关于构造器、render方法调用次数6 state简写7 问题解答后记1 state简介 Re…

在NVIDIA JetBot Nano小车上更新WIFI驱动

前言:树莓派上的WIFI驱动类型比较多,经常有更好驱动的需求本文给出RealTek的无线WIFI模组,8821CU的驱动更新办法步骤第一 通过其他方式连接网络小车通过网线或者老的WIFI连接到网络上第二 构建驱动模块并下载驱动首先,我们需要打开一个ubuntu…

【深度学习】BERT变体—RoBERTa

RoBERTa是的BERT的常用变体,出自Facebook的RoBERTa: A Robustly Optimized BERT Pretraining Approach。来自Facebook的作者根据BERT训练不足的缺点提出了更有效的预训练方法,并发布了具有更强鲁棒性的BERT:RoBERTa。 RoBERTa通过以下四个方面…

【JavaEE】基于mysql与servlet自制简易的表白墙程序

文章目录1 表白墙页面构建2 Servlet 回顾3 表白墙后端程序实现3.1 我们需要做什么?3.2 实现细节4 实现结果写在最后1 表白墙页面构建 该页面由标题、文本、三个 input 输入框与一个提交按钮构成,整体比较简单,相关样式文件和页面代码会在后面…

【16】linux命令每日分享——tail命令查看文件

大家好,这里是sdust-vrlab,Linux是一种免费使用和自由传播的类UNIX操作系统,Linux的基本思想有两点:一切都是文件;每个文件都有确定的用途;linux涉及到IT行业的方方面面,在我们日常的学习中&…

分布式中雪花算法

背景需要选择合适的方案去应对数据规模的增长,以应对逐渐增长的访问压力和数据量。 数据库的扩展方式主要包括:业务分库、主从复制,数据库分表。 2.数据库分表概念:将不同业务数据分散存储到不同的数据库服务器,能够支…

网络参考模型

OSI参考模型 应用层 不服务于任何其他层,就是位APP提供相应的服务,不如HTTP、域名解析DNS提供服务表示层 1.使得应用数据能够被不同的系统(Windows\Linux)进行识别和理解 2.数据的解码和编码、数据的加密与解密、数据的压缩和解…