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学习笔记(三)的更多相关文章
- JUC学习笔记(六)
		
JUC学习笔记(一)https://www.cnblogs.com/lm66/p/15118407.html JUC学习笔记(二)https://www.cnblogs.com/lm66/p/1511 ...
 - JUC学习笔记(五)
		
JUC学习笔记(一)https://www.cnblogs.com/lm66/p/15118407.html JUC学习笔记(二)https://www.cnblogs.com/lm66/p/1511 ...
 - JUC学习笔记(四)
		
JUC学习笔记(一)https://www.cnblogs.com/lm66/p/15118407.html JUC学习笔记(二)https://www.cnblogs.com/lm66/p/1511 ...
 - JUC学习笔记——进程与线程
		
JUC学习笔记--进程与线程 在本系列内容中我们会对JUC做一个系统的学习,本片将会介绍JUC的进程与线程部分 我们会分为以下几部分进行介绍: 进程与线程 并发与并行 同步与异步 线程详解 进程与线程 ...
 - JUC学习笔记——共享模型之管程
		
JUC学习笔记--共享模型之管程 在本系列内容中我们会对JUC做一个系统的学习,本片将会介绍JUC的管程部分 我们会分为以下几部分进行介绍: 共享问题 共享问题解决方案 线程安全分析 Monitor ...
 - JUC学习笔记——共享模型之内存
		
JUC学习笔记--共享模型之内存 在本系列内容中我们会对JUC做一个系统的学习,本片将会介绍JUC的内存部分 我们会分为以下几部分进行介绍: Java内存模型 可见性 模式之两阶段终止 模式之Balk ...
 - Oracle学习笔记三 SQL命令
		
SQL简介 SQL 支持下列类别的命令: 1.数据定义语言(DDL) 2.数据操纵语言(DML) 3.事务控制语言(TCL) 4.数据控制语言(DCL)
 - [Firefly引擎][学习笔记三][已完结]所需模块封装
		
原地址:http://www.9miao.com/question-15-54671.html 学习笔记一传送门学习笔记二传送门 学习笔记三导读: 笔记三主要就是各个模块的封装了,这里贴 ...
 - JSP学习笔记(三):简单的Tomcat Web服务器
		
注意:每次对Tomcat配置文件进行修改后,必须重启Tomcat 在E盘的DATA文件夹中创建TomcatDemo文件夹,并将Tomcat安装路径下的webapps/ROOT中的WEB-INF文件夹复 ...
 
随机推荐
- 飞扬起舞,基于.Net Cli亲手打造.Net Core团队的项目脚手架
			
什么是脚手架? Scaffolding is a meta-programming method of building database-backed software applications. ...
 - 4.5	RNN循环神经网络(recurrent neural network)
			
自己开发了一个股票智能分析软件,功能很强大,需要的点击下面的链接获取: https://www.cnblogs.com/bclshuai/p/11380657.html 1.1 RNN循环神经网络 ...
 - hive学习笔记之七:内置函数
			
欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...
 - ABP Framework:移除 EF Core Migrations 项目,统一数据上下文
			
原文:Unifying DbContexts for EF Core / Removing the EF Core Migrations Project 目录 导读:软件开发的一切都需要平衡 动机 警 ...
 - FreeRTOS+LVGL|Freertos+lvgl如何配置lvgl的心跳和任务管理器
			
目录 配置lvgl心跳(Tick) 配置lvgl任务管理器(Task Handler) LVGL中文手册 lvgl需要系统滴答声(心跳)才能知道动画和其他任务的经过时间,所以我们必须要配置好lvgl的 ...
 - DHCP与配置命令
			
1. DHCP简介 2. DHCP主要用途 3. 使用DHCP的好处 4.DHCP经典应用模式 5.DHCP交互过程 DHCP的IP地址自动获取工作原理 6.DHCP中继 应用场景 工作原理 ...
 - python 元组推导式
			
>>> b=(page for page in range(10))>>> print(b)<generator object <genexpr> ...
 - Grafana、Prometheus、mtail-日志监控
			
一:日志如何监控 在上一篇博客Grafana.Prometheus-监控平台中,简单了解了Grafana与Prometheus对项目做特定的监控打点,可视化的配置操作. 但是对于没有设置监控或者不容易 ...
 - IO流 connect reset
			
目录 出现场景 解决思路 出现场景 通过外部OBS下载10文件,然后通过工具将这10个文件打包成一个文件A.zip上传,最后将这个A.zip下载并解压,解压A.zip后发现文件数量不是10个. 解决思 ...
 - Spring RestTemplate 之exchange方法
			
●exchange方法提供统一的方法模板进行四种请求:POST,PUT,DELETE,GET (1)POST请求 String reqJsonStr = "{\"code\&quo ...