系列五、线程间通信

一、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.mfbz.cn/a/167201.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

EfficientPhys

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

Midjourney绘画提示词Prompt参考学习教程

一、工具 SparkAi&#xff1a; SparkAi创作系统是基于OpenAI很火的ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统&#xff0c;支持OpenAI-GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美&#xff0c;可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软…

nvm:轻松管理多个 Node 版本 | 开源日报 No.80

nvm-sh/nvm Stars: 67.6k License: MIT Node Version Manager&#xff0c;是一个 POSIX 兼容的 bash 脚本&#xff0c;用于管理多个活动 node.js 版本。nvm 可以让你通过命令行快速安装和使用不同版本的 Node。它可以在任何符合 POSIX 标准的 shell&#xff08;sh、dash、ksh…

YOLOv8-seg改进:SEAM、MultiSEAM分割物与物相互遮挡、分割小目标性能

🚀🚀🚀本文改进:SEAM、MultiSEAM分割物体与物体相互遮挡性能 🚀🚀🚀SEAM、MultiSEAM分割物与物相互遮挡、分割小目标性能 🚀🚀🚀YOLOv8-seg创新专栏:http://t.csdnimg.cn/KLSdv 学姐带你学习YOLOv8,从入门到创新,轻轻松松搞定科研; 1)手把手教你如何…

JSP协同办公eclipse定制开发mysql数据库BS模式java编程OA系统

一、源码特点 java 协同办公管理系统是一套完善的web设计系统 &#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,eclipse开发&#xff0c;数据库为Mysql5.0&#xff0c;使…

internet download manager2024中文绿色版(IDM下载器)

在现代互联网时代&#xff0c;文件下载已经成为我们日常生活中必不可少的一项技能。无论是下载软件、音乐、视频还是其他文件&#xff0c;一个高效的下载方法能够为我们节省时间和精力。本文将为您提供一份简明扼要的下载教程&#xff0c;让您轻松掌握文件下载的技巧。 intern…

【汇编】数据在哪里?有多长、div指令实现除法、dup设置内存空间

文章目录 前言一、汇编语言中数据位置的表达1.1 汇编中有哪几种数1.立即数&#xff08;idata&#xff09;&#xff1a;2.寄存器&#xff08;Register&#xff09;&#xff1a;3.内存&#xff08;Memory&#xff09;&#xff1a;4.段地址&#xff08;Segment Address&#xff0c…

NextJS开发:ssr服务器端渲染页面,添加加载进度提示

nextjs中ssr服务器端渲染的页面加载速度慢的时候&#xff0c;需要显示一个如下图的加载进度提示&#xff0c;来优化用户体验。 nextjs框架中已经预留了加载动画的接口页面&#xff0c;我们只需要提那家加载动画tsx&#xff0c;处理页面逻辑就可以实现。 page.tsx 同级目录创建…

ModernCSS.dev - 来自微软前端工程师的 CSS 高级教程,讲解如何用新的 CSS 语法来解决旧的问题

今天给大家安利一套现代 CSS 的教程&#xff0c;以前写网页的问题&#xff0c;现在都可以用新的写法来解决了。 ModernCSS.dev 是一个现代 CSS 语法的教程&#xff0c;讲解新的 CSS 语法如何解决一些传统问题&#xff0c;一共有30多课。 这套教程的作者是 Stephanie Eckles&am…

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

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

【canvas】了解canvas,并实现会议预定记录钟表盘、页面水印

初识canvas Canvas 有什么用 Canvas 允许使用直线、曲线、矩形、圆形等基本图形绘制出复杂的图形 Canvas 可以加载图像&#xff0c;并进行各种处理&#xff0c;如裁剪、缩放、旋转等操作 Canvas 可以通过 JavaScript 控制&#xff0c;所以你可以利用帧动画原理&#xff0c;…

Latex学习

二 实例 1. \Delta_{w}\frac{\partial l}{\partial w_{i1}}weight:\frac{\partial l}{\partial x_{i1}} 效果如下 其中对于希腊字母的大小写来说&#xff0c;可以参考&#xff1a; 【LaTeX 语法】字母表示 ( 大写、小写、异体 希腊字母 | 粗体字母 | 花体字母 )_latex字母_韩…

大白话解释什么类加载机制

大家好&#xff0c;我是伍六七。 今天我们来聊聊一个 Java 面试必考基础题目&#xff1a;类加载机制和双亲委派机制。 Java 类的加载机制是 Java 虚拟机&#xff08;JVM&#xff09;中类加载&#xff08;Class Loading&#xff09;和链接&#xff08;Linking&#xff09;的过…

RT-DETR优化改进:SEAM、MultiSEAM分割物与物相互遮挡、分割小目标性能

🚀🚀🚀本文改进:SEAM、MultiSEAM分割物体与物体相互遮挡性能 🚀🚀🚀SEAM、MultiSEAM分割物与物相互遮挡、分割小目标性能 🚀🚀🚀RT-DETR改进创新专栏:http://t.csdnimg.cn/vuQTz 学姐带你学习YOLOv8,从入门到创新,轻轻松松搞定科研; RT-DETR模型创新…

【cpolar】搭建我的世界Java版服务器,公网远程联机

&#x1f3a5; 个人主页&#xff1a;深鱼~&#x1f525;收录专栏&#xff1a;cpolar&#x1f304;欢迎 &#x1f44d;点赞✍评论⭐收藏 目录 前言&#xff1a; 1. 搭建我的世界服务器 1.1 服务器安装java环境 1.2 配置服务端 2. 测试局域网联机 3. 公网远程联机 3.1 安…

数字IC前端学习笔记:时钟切换电路

相关阅读 数字IC前端https://blog.csdn.net/weixin_45791458/category_12173698.html?spm1001.2014.3001.5482 有些时候我们需要在系统运行时切换系统时钟&#xff0c;最简单的方法就是使用一个MUX&#xff08;数据选择器&#xff09;选择输出的时钟&#xff0c;如下代码片所…

【C++】​——多态性与模板(其一)

&#x1f383;个人专栏&#xff1a; &#x1f42c; 算法设计与分析&#xff1a;算法设计与分析_IT闫的博客-CSDN博客 &#x1f433;Java基础&#xff1a;Java基础_IT闫的博客-CSDN博客 &#x1f40b;c语言&#xff1a;c语言_IT闫的博客-CSDN博客 &#x1f41f;MySQL&#xff1a…

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

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

MySQL数据库入门到大牛_基础_09_子查询(子查询分类方法;单行子查询,多行子查询;相关子查询)

前面的第三章到第八章中&#xff0c;我们讲的是查询&#xff0c;查询的基本结构已经进行了介绍&#xff0c;聚合函数学习完后已经介绍了查询语句的完整的执行流程。 子查询指一个查询语句嵌套在另一个查询语句内部的查询&#xff0c;这个特性从MySQL 4.1开始引入。本章也是查询…

【开源】基于JAVA的校园二手交易系统

项目编号&#xff1a; S 009 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S009&#xff0c;文末获取源码。} 项目编号&#xff1a;S009&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 二手商品档案管理模…