系列五、线程间通信

news2024/11/14 15:23:55

一、synchronized实现

1.1、案例一(2个线程交替对变量执行+1、-1操作,来10轮)

1.1.1、资源类ShareDataOne

/**
 * @Author : 一叶浮萍归大海
 * @Date: 2023/11/20 10:44
 * @Description: 资源类
 * 说明:2个线程使用if判断变量的值,没有问题,3个及3个以上线程会出现虚假唤醒的问题,需要注意!!!!!
 */
public class ShareDataOne {
    private int number = 0;

    /**
     * 加1
     *
     * @throws InterruptedException
     */
    public synchronized void increment() throws InterruptedException {
        // 1、判断
        if (number != 0) {
            this.wait();
        }

        // 2、干活
        ++number;
        System.out.println(Thread.currentThread().getName() + "\t" + number);

        // 3、通知
        this.notifyAll();
    }

    /**
     * 减1
     *
     * @throws InterruptedException
     */
    public synchronized void decrement() throws InterruptedException {
        // 1、判断
        if (number == 0) {
            this.wait();
        }

        // 2、干活
        --number;
        System.out.println(Thread.currentThread().getName() + "\t" + number);

        // 3、通知
        this.notifyAll();
    }
}

1.1.2、线程类ShareDataOneMainApp

/**
 * @Author : 一叶浮萍归大海
 * @Date: 2023/11/20 10:46
 * @Description:
 * 需求:两个线程,可以操作初始量为零的一个变量,实现一个线程对该变量加1,一个线程对该变量减1,交替来10轮
 * Java里边如何进行工程级别的多线程编写?
 *      1、多线程编程模板(套路上)
 *          1.1、线程 操作 资源类
 *          1.2、高内聚 低耦合
 *
 *      2、多线程编程模板(套路下)
 *          2.1、判断
 *          2.2、干活
 *          2.3、通知
 *
 *      3、防止虚假唤醒用while
 */
public class ShareDataOneMainApp {

    public static void main(String[] args) {
        ShareDataOne sd = new ShareDataOne();

        new Thread(() -> {
            for (int i = 1; i <= 10; i++) {
                try {
                    sd.increment();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }, "A").start();

        new Thread(() -> {
            for (int i = 1; i <= 10; i++) {
                try {
                    sd.decrement();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }, "B").start();

    }

}

1.1.3、结果

1.2、案例二(4个线程交替对变量执行+1、-1操作,来10轮) 

1.2.1、资源类ShareDataTwo

/**
 * @Author : 一叶浮萍归大海
 * @Date: 2023/11/20 10:44
 * @Description: 资源类
 * 说明:2个线程使用if判断变量的值,没有问题,3个及3个以上线程会出现虚假唤醒的问题,需要注意!!!!!
 * 解决方法:使用while做判断条件
 * 原理:中断和虚假唤醒是由可能产生的,所以要用loob循环,if只判断一次,while是只要唤醒就要拉回来再判断一次,if换成while即可解决虚假唤醒的问题
 */
public class ShareDataTwo {
    private int number = 0;

    /**
     * 加1
     *
     * @throws InterruptedException
     */
    public synchronized void increment() throws InterruptedException {
        // 1、判断
        while (number != 0) {
            this.wait();
        }

        // 2、干活
        ++number;
        System.out.println(Thread.currentThread().getName() + "\t" + number);

        // 3、通知
        this.notifyAll();
    }

    /**
     * 减1
     *
     * @throws InterruptedException
     */
    public synchronized void decrement() throws InterruptedException {
        // 1、判断
        while (number == 0) {
            this.wait();
        }

        // 2、干活
        --number;
        System.out.println(Thread.currentThread().getName() + "\t" + number);

        // 3、通知
        this.notifyAll();
    }
}

1.2.2、线程类

/**
 * @Author : 一叶浮萍归大海
 * @Date: 2023/11/20 11:19
 * @Description:
 * 需求:四个线程,可以操作初始量为零的一个变量,实现一个线程对该变量加1,一个线程对该变量减1,交替来10轮
 * Java里边如何进行工程级别的多线程编写?
 *      1、多线程编程模板(套路上)
 *          1.1、线程 操作 资源类
 *          1.2、高内聚 低耦合
 *
 *      2、多线程编程模板(套路下)
 *          2.1、判断
 *          2.2、干活
 *          2.3、通知
 *
 *      3、防止虚假唤醒用while
 */
public class ShareDataTwoMainApp {

    public static void main(String[] args) {
        ShareDataTwo sdt = new ShareDataTwo();

        new Thread(() -> {
        	for (int i = 1; i <= 10; i++) {
        		try {
                    sdt.increment();
        		} catch (Exception e) {
        		    e.printStackTrace();
        		}
        	}
        }, "A").start();

        new Thread(() -> {
            for (int i = 1; i <= 10; i++) {
                try {
                    sdt.decrement();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }, "B").start();

        new Thread(() -> {
            for (int i = 1; i <= 10; i++) {
                try {
                    sdt.increment();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }, "C").start();

        new Thread(() -> {
            for (int i = 1; i <= 10; i++) {
                try {
                    sdt.decrement();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }, "D").start();
    }

}

1.2.3、结果

二、Condition实现

2.1、案例一(2个线程交替对变量执行+1、-1操作,来10轮)

2.1.1、资源类ShareDataThree

/**
 * @Author : 一叶浮萍归大海
 * @Date: 2023/11/20 11:40
 * @Description: 资源类
 * 说明:2个线程使用if判断变量的值,没有问题,3个及3个以上线程会出现虚假唤醒的问题,需要注意!!!!!
 * 解决方法:使用while做判断条件
 * 原理:中断和虚假唤醒是由可能产生的,所以要用loob循环,if只判断一次,while是只要唤醒就要拉回来再判断一次,if换成while即可解决虚假唤醒的问题
 */
public class ShareDataThree {

    private Integer number = 0;

    private Lock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();

    /**
     * 加1
     */
    public void increment() {
        lock.lock();
        try {
            // 判断
            while (number != 0) {
                condition.await();
            }

            // 干活
            ++number;
            System.out.println(Thread.currentThread().getName() + "\t" + number);

            // 通知
            condition.signalAll();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    /**
     * 加1
     */
    public void decrement() {
        lock.lock();
        try {
            // 判断
            while (number == 0) {
                condition.await();
            }

            // 干活
            --number;
            System.out.println(Thread.currentThread().getName() + "\t" + number);

            // 通知
            condition.signalAll();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

}

2.1.2、线程类ShareDataThreeMainApp

/**
 * @Author : 一叶浮萍归大海
 * @Date: 2023/11/20 11:19
 * @Description:
 * 需求:两个线程,可以操作初始量为零的一个变量,实现一个线程对该变量加1,一个线程对该变量减1,交替来10轮
 * Java里边如何进行工程级别的多线程编写?
 *      1、多线程编程模板(套路上)
 *          1.1、线程 操作 资源类
 *          1.2、高内聚 低耦合
 *
 *      2、多线程编程模板(套路下)
 *          2.1、判断
 *          2.2、干活
 *          2.3、通知
 *
 *      3、防止虚假唤醒用while
 */
public class ShareDataThreeMainApp {

    public static void main(String[] args) {
        ShareDataThree sdt = new ShareDataThree();

        new Thread(() -> {
        	for (int i = 1; i <= 10; i++) {
        		try {
                    sdt.increment();
        		} catch (Exception e) {
        		    e.printStackTrace();
        		}
        	}
        }, "A").start();

        new Thread(() -> {
            for (int i = 1; i <= 10; i++) {
                try {
                    sdt.decrement();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }, "B").start();

    }

}

 2.1.3、结果

2.2、案例二(4个线程交替对变量执行+1、-1操作,来10轮) 

2.2.1、资源类ShareDataThree

同2.1.1。

2.2.2、线程类

/**
 * @Author : 一叶浮萍归大海
 * @Date: 2023/11/20 11:19
 * @Description:
 * 需求:四个线程,可以操作初始量为零的一个变量,实现一个线程对该变量加1,一个线程对该变量减1,交替来10轮
 * Java里边如何进行工程级别的多线程编写?
 *      1、多线程编程模板(套路上)
 *          1.1、线程 操作 资源类
 *          1.2、高内聚 低耦合
 *
 *      2、多线程编程模板(套路下)
 *          2.1、判断
 *          2.2、干活
 *          2.3、通知
 *
 *      3、防止虚假唤醒用while
 */
public class ShareDataFourMainApp {

    public static void main(String[] args) {
        ShareDataThree sdt = new ShareDataThree();

        new Thread(() -> {
        	for (int i = 1; i <= 10; i++) {
        		try {
                    sdt.increment();
        		} catch (Exception e) {
        		    e.printStackTrace();
        		}
        	}
        }, "A").start();

        new Thread(() -> {
            for (int i = 1; i <= 10; i++) {
                try {
                    sdt.decrement();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }, "B").start();

        new Thread(() -> {
            for (int i = 1; i <= 10; i++) {
                try {
                    sdt.increment();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }, "C").start();

        new Thread(() -> {
            for (int i = 1; i <= 10; i++) {
                try {
                    sdt.decrement();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }, "D").start();

    }

}

2.2.3、结果

三、线程间定制化通信

3.1、资源类ShareDataFive

/**
 * @Author : 一叶浮萍归大海
 * @Date: 2023/11/20 12:12
 * @Description: 资源类
 * 说明:2个线程使用if判断变量的值,没有问题,3个及3个以上线程会出现虚假唤醒的问题,需要注意!!!!!
 * 解决方法:使用while做判断条件
 * 原理:中断和虚假唤醒是由可能产生的,所以要用loob循环,if只判断一次,while是只要唤醒就要拉回来再判断一次,if换成while即可解决虚假唤醒的问题
 */
public class ShareDataFive {
    private Integer number = 1;
    private Lock lock = new ReentrantLock();
    private Condition condition1 = lock.newCondition();
    private Condition condition2 = lock.newCondition();
    private Condition condition3 = lock.newCondition();

    public void print5(int totalLoopNumber) {
        lock.lock();
        try {
            // 判断
            while (number != 1) {
                condition1.await();
            }
            // 干活
            for (int i = 1; i <= totalLoopNumber; i++) {
                System.out.println("【当前线程】:" + Thread.currentThread().getName() + ",【当前i的值】:" + i + ",【totalLoopNumber】:" + totalLoopNumber);
            }
            // 通知
            number = 2;
            condition2.signal();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public void print10(int totalLoopNumber) {
        lock.lock();
        try {
            // 判断
            while (number != 2) {
                condition2.await();
            }
            // 干活
            for (int i = 1; i <= totalLoopNumber; i++) {
                System.out.println("【当前线程】:" + Thread.currentThread().getName() + ",【当前i的值】:" + i + ",【totalLoopNumber】:" + totalLoopNumber);
            }
            // 通知
            number = 3;
            condition3.signal();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public void print15(int totalLoopNumber) {
        lock.lock();
        try {
            // 判断
            while (number != 3) {
                condition3.await();
            }
            // 干活
            for (int i = 1; i <= totalLoopNumber; i++) {
                System.out.println("【当前线程】:" + Thread.currentThread().getName() + ",【当前i的值】:" + i + ",【totalLoopNumber】:" + totalLoopNumber);
            }
            // 通知
            number = 1;
            condition1.signal();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}

3.2、线程类

/**
 * @Author : 一叶浮萍归大海
 * @Date: 2023/11/20 12:22
 * @Description: 需求:多个线程之间按顺序调用,实现AA>BB>CC,三个线程启动,
 * 要求:
 * AA打印5次,BB打印10次,CC打印15次
 * 接着,AA打印5次,BB打印10次,CC打印15次
 * ...
 * 来10轮
 */
public class ShareDataFiveMainApp {

    public static void main(String[] args) {
        ShareDataFive sdf = new ShareDataFive();

        new Thread(() -> {
            for (int i = 1; i <= 10; i++) {
                sdf.print5(5);
            }
        }, "AA").start();

        new Thread(() -> {
            for (int i = 1; i <= 10; i++) {
                sdf.print10(10);
            }
        }, "BB").start();

        new Thread(() -> {
            for (int i = 1; i <= 10; i++) {
                sdf.print15(15);
            }
        }, "CC").start();
    }

}

3.3、结果

 

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

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

相关文章

Python中用requests时遇到的错误警告解决方案

最近&#xff0c;我在Python 2.7.6&#xff08;Ubuntu 14.04.2 LTS&#xff09;环境中将requests库的版本从2.5.3升级到2.6.0&#xff0c;却遇到了’A true SSLContext object is not available’警告。每当我在Python 2.7.6环境中尝试使用requests库访问’github’时&#xff…

论文笔记:The Impact of AI on Developer Productivity:Evidence from GitHub Copilot

0 abstract 本文介绍了一项对GitHub Copilot&#xff08;一种人工智能编程助手&#xff09;的控制实验结果。研究人员招募了软件开发人员&#xff0c;要求他们尽可能快地用JavaScript实现一个HTTP服务器。实验组可以访问人工智能编程助手&#xff0c;比对照组完成任务的速度快…

Python 进程和线程详解(multiprocessing、threading)

文章目录 1 概述1.1 进程 VS 线程1.2 优缺点 2 进程2.1 三个步骤2.2 多进程2.3 带参数2.3.1 元组参数 args2.3.2 字典参数 kwargs 2.4 获取进程编号2.5 设置进程守护 3 线程3.1 三个步骤3.2 多线程3.3 带参数2.3.1 元组参数 args2.3.2 字典参数 kwargs 2.4 获取线程编号2.5 设置…

python爬取快手视频

原理 F12点击graphql能够看到里面有若干视频信息,一会儿要取其中的url地址 右键复制cURL 然后进入到这个转换器连接 https://curlconverter.com/python/ 点击这个连接复制上述信息,然后就能解析处下面的代码,拷贝到你的项目中替换cookies,headers,json_data 源代码 …

大模型重塑软件设计,南京真我加入飞桨技术伙伴,大模型生态圈成员又添一员!

为帮助伙伴更快、更好的应用大模型技术&#xff0c;飞桨技术伙伴体系及权益基于星河共创计划全面升级&#xff0c;通过丰富的场景、技术、算力、品牌等资源&#xff0c;为伙伴企业提供一站式的大模型资源对接&#xff0c;全面降低创建AI原生应用的门槛。 近日&#xff0c;南京…

QQ自动批量加好友(手机端)

1.需求 按照格式输入批量qq号,输入加好友间隔时间,脚本自动打开qq应用开始自动加好友,全程自动化操作。 输入qq号格式: 运行示意图: 2.代码 function carmiLogin () {var carmi = getCarMi()try {const data = {"key": carmi}http.__okhttp__.setTimeout(3000…

「Verilog学习笔记」边沿检测

专栏前言 本专栏的内容主要是记录本人学习Verilog过程中的一些知识点&#xff0c;刷题网站用的是牛客网 timescale 1ns/1ns module edge_detect(input clk,input rst_n,input a,output reg rise,output reg down );reg a_tem ; always (posedge clk or negedge rst_n) beginif…

2023年中国负极材料分类、产量及市场规模分析[图]

锂离子电池主要由正极、负极、隔膜、电解液、电池外壳组成。负极材料是锂离子电池的重要原材料之一&#xff0c;对于锂离子电池起关键作用。在充电过程负极材料中不断地与锂离子发生反应&#xff0c;将锂离子“擒获并存储”起来&#xff0c;亦将外部的功以能量的形式存储在电池…

Leetcode2937. 使三个字符串相等

Every day a Leetcode 题目来源&#xff1a;2937. 使三个字符串相等 解法1&#xff1a;枚举 设 len1、len2、len3 分别为字符串 s1、s2、s3 的长度。 min_len 是 3 个字符串长度的最小值。 枚举 len min_len 到 len 1&#xff0c;设 t1、t2、t3 分别是字符串 s1、s2、s…

富友支付最近“战况”

中国人民银行上海市分行官网在昨天披露了一份关于富友支付的行政处罚公示信息。富友支付因为涉嫌违法违规的反洗钱行为而遭到中国央行的罚款。 罚款金额达到455万&#xff0c;可谓相当可观。 当支付机构受到罚款处罚时&#xff0c;一些公司会选择在收到罚单后发表声明&#xff…

Node.js黑马时钟案例(本人详细介绍实现过程)

先上没有使用node.js之前的html部分代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title></title><style>* {margin: 0;padding: 0;}html,body {height: 100%;overflow: hidden;backgrou…

「Verilog学习笔记」ROM的简单实现

专栏前言 本专栏的内容主要是记录本人学习Verilog过程中的一些知识点&#xff0c;刷题网站用的是牛客网 分析 要实现ROM&#xff0c;首先要声明数据的存储空间&#xff0c;例如&#xff1a;[3:0] rom [7:0]&#xff1b;变量名称rom之前的[3:0]表示每个数据具有多少位&#xff0…

EfficientPhys

研究背景 基于相机的生理测量是一种非接触式方法&#xff0c;用于通过从身体反射的光捕获心脏信号。最常见的此类信号是通过光电体积描记图 (PPG) 测量的血容量脉搏 (BVP)。由此&#xff0c;可以推导出心率、呼吸率和脉搏传导时间。神经网络模型是当前最先进的 rPPG 测量方式。…

Rapid chain

这篇文章中提到 Elastico 运行6个epoch就会退化到公式失败率高达 0.97 omnileger 在第一个epoch需要一个初始化的随机种子&#xff0c;来初始化 VRF。这需要 O ( n 2 ) O(n^2) O(n2) 的复杂度&#xff0c;并且OminLedger 需要通过轻节点驱动枷锁和解锁的过程&#xff0c;这户家…

2023年中国中端连锁酒店分类、市场规模及主要企业市占率[图]

中端连锁酒店行业是指定位于中档酒店市场、具有全国统一的品牌形象识别系统、全国统一的运营体系、会员体系和营销体系的酒店。中端酒店通常提供舒适、标准化的房间设施和服务&#xff0c;价格较为合理&#xff0c;符合广大消费者的需求。其价格略高于经济型酒店&#xff0c;但…

【数字图像处理】Gamma 变换

在数字图像处理中&#xff0c;Gamma 变换是一种重要的灰度变换方法&#xff0c;可以用于图像增强与 Gamma 校正。本文主要介绍数字图像 Gamma 变换的基本原理&#xff0c;并记录在紫光同创 PGL22G FPGA 平台的布署与实现过程。 目录 1. Gamma 变换原理 2. FPGA 布署与实现 2…

unity-模块卸载重新安装

unity-模块卸载重新安装 发现模块错误&#xff1f;发现不可以卸载重装&#xff1f;... 依据以下步骤试试&#xff1a; 1. 删除模块文件夹&#xff08;以安卓模块为例&#xff09; 2. 找见编辑器模块json 3. 找见所有安卓相关模块修改selected为false&#xff1a;"sel…

2023年中国地产SaaS分类、产业链及市场规模分析[图]

SaaS是一种基于云计算技术&#xff0c;通过订阅的方式向互联网向客户提供访问权限以获取计算资源的一项软件即服务。地产SaaS则是SaaS的具体应用&#xff0c;提供了一个线上平台&#xff0c;用于协助房地产供应商与购房者、建筑承建商、材料供应商及房地产资产管理公司之间的协…

Kotlin学习——hello kotlin 函数function 变量 类 + 泛型 + 继承

Kotlin 是一门现代但已成熟的编程语言&#xff0c;旨在让开发人员更幸福快乐。 它简洁、安全、可与 Java 及其他语言互操作&#xff0c;并提供了多种方式在多个平台间复用代码&#xff0c;以实现高效编程。 https://play.kotlinlang.org/byExample/01_introduction/02_Functio…

5G与中国的海

今年国庆假期&#xff0c;香港迎来了阔别5年的国庆维港烟花汇演 10月1日晚上9点&#xff0c;“HKT x FWD 2023 年国庆烟花汇演”在维多利亚港上空上演。在23分钟时间里&#xff0c;燃放了超过3万枚烟花。而与以往维港烟花秀不同的是&#xff0c;为了让更多民众欣赏这次表演&…