JUC学习笔记(三)

JUC学习笔记(三)

线程间通信的模型有两种:共享内存和消息传递,以下方式都是基本这两种模型来实现的。我们来基本一道面试常见的题目来分析

JUC学习笔记(一)https://www.cnblogs.com/lm66/p/15118407.html
JUC学习笔记(二)https://www.cnblogs.com/lm66/p/15118813.html

1、线程间通信

线程间通信的模型有两种:共享内存和消息传递,以下方式都是基本这两种模型来实现的。我们来基本一道面试常见的题目来分析
场景—两个线程,一个线程对当前数值加 1,另一个线程对当前数值减 1,要求用线程间通信

1.1、synchronized 方案

public class ThreadDemo1 {

    public static void main(String[] args) {
        Share share = new Share();

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

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

}

class Share {

    private int num = 0;

    public synchronized void increment() throws Exception {
        while (num != 0) {
            this.wait();
        }
        num++;
        System.out.println(Thread.currentThread().getName() + "::" + num);
        this.notifyAll();

    }

    public synchronized void decrement() throws Exception {
        while (num != 1) {
            this.wait();
        }
        num--;
        System.out.println(Thread.currentThread().getName() + "::" + num);
        this.notifyAll();
    }
}

1.2、Lock方案

public class ThreadDemo2 {

    public static void main(String[] args) {
        Share2 share = new Share2();

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

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

}

class Share2 {

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

    private int num = 0;

    public void increment() throws Exception {
        lock.lock();
        try {
            while (num != 0) {
                condition.await();
            }
            num++;
            System.out.println(Thread.currentThread().getName() + "::" + num);
            condition.signalAll();
        } finally {
            lock.unlock();
        }

    }

    public void decrement() throws Exception {
        lock.lock();
        try {
            while (num != 1) {
                condition.await();
            }
            num--;
            System.out.println(Thread.currentThread().getName() + "::" + num);
            condition.signalAll();
        } finally {
            lock.unlock();
        }
    }
}

1.3、线程间定制化通信

1.3.1、案例介绍

问题: A 线程打印 5 次 A,B 线程打印 10 次 B,C 线程打印 15 次 C,按照此顺序循环 10 轮

1.3.2、实现流程

public class ThreadDemo3 {

    public static void main(String[] args) {
        ShareResource shareResource = new ShareResource();
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                try {
                    shareResource.print5(i);
                } catch (Exception e) {
                }
            }
        },"AA").start();
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                try {
                    shareResource.print10(i);
                } catch (Exception e) {
                }
            }
        },"BB").start();
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                try {
                    shareResource.print15(i);
                } catch (Exception e) {
                }
            }
        },"CC").start();
    }
}

class ShareResource {
    // 定义标志位
    private int flag = 1;
    // 创建Lock锁
    private Lock lock = new ReentrantLock();
    private Condition c1 = lock.newCondition();
    private Condition c2 = lock.newCondition();
    private Condition c3 = lock.newCondition();

    public void print5(int loop) throws Exception {
        lock.lock();
        try {
            // 判断。防止虚假唤醒
            while (flag != 1) {
                // 等待
                c1.await();
            }
            for (int i = 0; i < 5; i++) {
                System.out.println(Thread.currentThread().getName() + "::" + loop);
            }
            // 修改标志位
            flag = 2;
            // 通知
            c2.signal();
        } finally {
            lock.unlock();
        }
    }

    public void print10(int loop) throws Exception {
        lock.lock();
        try {
            while (flag != 2) {
                c2.await();
            }
            for (int i = 0; i < 10; i++) {
                System.out.println(Thread.currentThread().getName() + "::" + loop);
            }
            flag = 3;
            c3.signal();
        } finally {
            lock.unlock();
        }
    }

    public void print15(int loop) throws Exception {
        lock.lock();
        try {
            while (flag != 3) {
                c3.await();
            }
            for (int i = 0; i < 15; i++) {
                System.out.println(Thread.currentThread().getName() + "::" + loop);
            }
            flag = 1;
            c1.signal();
        } finally {
            lock.unlock();
        }
    }
}

JUC学习笔记(三)

Original: https://www.cnblogs.com/lm66/p/15118976.html
Author: Liming_Code
Title: JUC学习笔记(三)

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/576005/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • DDD(Domain Driver Design)领域驱动模型

    Domain Primitive(DP) DP概念DP 是 DDD 中的一个基础概念,是 DDD 中可以执行的一个最小单元,最直接的体现是,将业务相关的参数定义在一个特定的领域中(…

    数据库 2023年6月6日
    0133
  • 机器学习—神经网络

    BP神经网络的综述 1.1神经网络的定义 神经网络(neural network) 是由具有适应性的简单单元组成的广泛并行互连的网络,它的组织能够模拟生物神经系统对真实世界物体所做…

    数据库 2023年6月16日
    083
  • Struts 2 学习笔记

    Struts2 是一个基于 MVC 设计模式的 Web 应用框架,它本质上相当于一个 servlet,在 MVC 设计模式中,Struts2 作为控制器(Controller)来建…

    数据库 2023年6月11日
    092
  • MySQL 安全管理

    权限表 MySQL 服务器通过权限表来控制用户对数据库的访问,由 mysql_install_db 脚本初始化,MySQL 会根据这些权限表的内容为每个用户赋予相应的权限 user…

    数据库 2023年5月24日
    089
  • Linux日志管理

    日志管理 日志文件 日志文件是重要的系统信息文件,其中记录了许多重要的系统事件,包括用户的登录信息、系统的启动信息、系统的安全信息、邮件相关信息、各种服务相关信息等。日志对于安全来…

    数据库 2023年6月16日
    089
  • 牛客SQL刷题第三趴——SQL必知必会

    【问题】编写 SQL 语句,从 Products 表中检索产品名称(prod_name)和描述(prod_desc),仅返回在描述中以先后顺序同时出现 toy 和 carrots …

    数据库 2023年6月16日
    0101
  • Spring常见问题

    Spring常见问题 问渠那得清如许?为有源头活水来。 Spring 是个 java 企业级应用的开源开发框架。Spring 主要用来开发 Java 应用,但是有些扩展是针对构建 …

    数据库 2023年6月14日
    083
  • 4 String是基本数据类型吗

    不是,Java中的基本类型只有8种,分别是:byte,short,int,long,float,double,char,boolean; 除了以上8种基本数据类型以外,其余的均为引…

    数据库 2023年6月6日
    081
  • 力扣数据库题目627变更性别

    力扣数据库题目627变更性别 给定一个 salary 表,如下所示,有 m = 男性 和 f = 女性 的值。交换所有的 f 和 m 值(例如,将所有 f 值更改为 m,反之亦然)…

    数据库 2023年6月9日
    061
  • 常见的dos命令

    常用快捷键 alt+f4 常见的dos命令 打开CMD的方式 开始+系统+命令提示符 win+R 输入cmd打开控制台 在任意文件夹下,按住shift+鼠标右键点击 资源管理器的地…

    数据库 2023年6月11日
    0103
  • MySQL高可用安装

    MySQL HA部署 环境准备 创建本地yum源 确认关闭 SELinux 防火墙设置 MySQL安装 使用 root 用户操作创建相关的用户组和用户 上传/解压介质 设置自启动 …

    数据库 2023年5月24日
    0108
  • MySQL中的触发器

    1.定义: 触发器和存储过程相似,都是嵌入到 MySQL 中的一段程序。触发器是由事件来触发某个操作。当数据库执行这些事件时,就会激活触发器来执行相应的操作。这些事件称为触发条件,…

    数据库 2023年6月16日
    0115
  • mydumper备份mysql8.0 sql thread被kill掉

    这个问题是好久以前的问题了,今天看自己的笔记,发现了这个问题,当时没有进行细看,想着现在复现一下。 1、半夜收到测试数据库备份告警: 报警内容就是8002端口,备份失败,因为有慢查…

    数据库 2023年6月16日
    088
  • linux中如何查找一个文件夹的大小呢?

    1、(方法一)ls -lht会列出当前目录下每个文件的大小,同时也会给出当前目录下所有文件大小总和 2、(方法二)du -sh *也会列出当前文件夹下所有文件对应的大小 【把*替换…

    数据库 2023年6月11日
    0104
  • Golang context

    Context Go 语言中提供了 context 包,通过显示传递 context, 实现请求级别的元数据、取消信号、终止信号的传递。context 包提供了从现有的上下文值(c…

    数据库 2023年6月16日
    090
  • 设计模式之(6)——建造者模式

    定义:建造者模式也称为生成器模式,将一个个简单对象一步步构造成一个复杂的对象,将复杂对象的构建和它的表示分离,使得同样的构建过程有不同的表示; 主要解决:系统中复杂对象的创建过程,…

    数据库 2023年6月14日
    080
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球