目录

例题1:交替输出

Park和unpark交替输出

固定顺序:一个线程唤醒另一现场用wait和notify

ReentrantLock条件变量例题:抽烟和外卖的工作

总结:


例题1:交替输出

今天突然发现notifyAll()能唤醒当前线程(也就是当前线程也能自抢)

package com.example.juc.ReengtrantLock.Alternate;import lombok.extern.slf4j.Slf4j;/*** @author diao 2022/4/13*/
//一个交替输出
@Slf4j(topic = "c.Test01")
public class Test01 {public static void main(String[] args) {WaitNotify wn = new WaitNotify(1, 5);new Thread(()->{log.debug("开始t1");wn.print("a",1,2);},"t1").start();new Thread(()->{log.debug("开始t2");wn.print("b",2,3);},"t2").start();new Thread(()->{log.debug("开始t3");wn.print("c",3,1);},"t3").start();}
}/*** 当做完一个线程,标记值发生改变,以此切换到其他线程*/
@Slf4j(topic = "c.WaitNotify")
class WaitNotify{/*** 根据线程打印内容* @param str:字符串内容* @param waitFlag:等待标记* @param nextFlag:下一个标记*/public void print(String str,int waitFlag,int nextFlag){for (int i = 0; i < loopNumber; i++) {//2.上锁synchronized (this){/*2.1比较标记是否相同,因为我们是对这个标记上锁*/while(flag!=waitFlag){try {log.debug("进入等待");/*2.2不是一样的话,就释放锁资源给其他线程使用*/this.wait();} catch (InterruptedException e) {e.printStackTrace();}}log.debug("str[{}]",str);/*2.3让下一个线程运行,等待标记flag到下一个,然后唤醒等待线程*/flag=nextFlag;/*2.4注意这里唤醒其他线程,就直接去执行了*/this.notifyAll();}}}//1.等待标记private int flag; //标记值1,2,3//2.循环次数private int loopNumber;public WaitNotify(int flag, int loopNumber) {this.flag = flag;this.loopNumber = loopNumber;}
}

说明当前线程锁资源调用的notifyAll唤醒的是当前线程本身,而flag已经+1所以陷入等待,wait后,t3竞争到资源....


Park和unpark交替输出

package com.example.juc.ReengtrantLock.Alternate;import lombok.extern.slf4j.Slf4j;import java.util.concurrent.locks.LockSupport;/*** @author diao 2022/4/13*/
@Slf4j(topic = "c.Test02")
public class Test02 {static Thread t1;static Thread t2;static Thread t3;public static void main(String[] args) {ParkUnpark pu = new ParkUnpark(5);t1=new Thread(()->{//1.第一个线程打印a,唤醒t2线程pu.print("a",t2);});t2=new Thread(()->{pu.print("b",t3);});t3=new Thread(()->{pu.print("c",t3);});t1.start();t2.start();t3.start();//唤醒t1线程,使其可以打印了LockSupport.unpark(t1);}
}@Slf4j(topic = "c.ParkUnpark")
class ParkUnpark{public void print(String str,Thread next){for (int i = 0; i < loopNumber; i++) {//暂停当前线程log.debug("第"+i+"次开始暂停");LockSupport.park();log.debug("str[{}]",str);//唤醒下一个线程log.debug("唤醒下一个线程");LockSupport.unpark(next);}}private int loopNumber;public ParkUnpark(int loopNumber) {this.loopNumber = loopNumber;}
}


固定顺序:一个线程唤醒另一现场用wait和notify

package com.example.juc.ReengtrantLock;import lombok.extern.slf4j.Slf4j;import static java.lang.Thread.sleep;/*** @author diao 2022/4/13*/
@Slf4j(topic = "c.orderTest")
public class orderTest {//1.定义一个锁对象static final Object lock=new Object();static boolean t2runned=false;public static void main(String[] args) throws InterruptedException {Thread t1=new Thread(()->{//2.0开始上锁synchronized (lock) {log.debug("获取synchronized的锁资源");//2.1判断是否执行,防止虚假唤醒while (!t2runned) {try {log.debug("开始进入等待");//开始等待lock.wait();log.debug("t1被唤醒");} catch (InterruptedException e) {e.printStackTrace();}}}log.debug("打印1");},"t1");sleep(1000);Thread t2=new Thread(()->{synchronized (lock) {log.debug("2");//2.改变状态t2runned=true;lock.notify();}},"t2");t1.start();t2.start();}
}


ReentrantLock条件变量例题:抽烟和外卖的工作

package com.example.juc.ReengtrantLock;import lombok.extern.slf4j.Slf4j;import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;import static java.lang.Thread.sleep;/*** @author diao 2022/4/13*/
@Slf4j(topic = "c.Test24")
public class Test24 {static final Object room=new Object();static boolean hasCigarette=false;static boolean hasTakeOut=false;static ReentrantLock ROOM=new ReentrantLock();/*** Condition的newCondition()方法由ReentrantLock对象调用* ——>得到Condition对象:可以实现等待和通知* 1.await():相当于synchronized锁中锁对象调用wait()方法* 2.*///等待烟的休息室static Condition waitCigaretteSet=ROOM.newCondition();//等待外卖的休息室static Condition waitTakeOutSet=ROOM.newCondition();public static void main(String[] args) throws InterruptedException {new Thread(()->{/*1.获取ReentrantLock的锁资源*/ROOM.lock();/*2.加锁和释放锁需要再try-finally中实现*/try {log.debug("有烟没?[{}]",hasCigarette);/*2.1用一个循环进行判断,防止虚假唤醒*/while(!hasCigarette){log.debug("没烟,先休息会");try {waitCigaretteSet.await();} catch (InterruptedException e) {e.printStackTrace();}}//后面如果被唤醒会再次询问log.debug("有烟没?[{}]",hasCigarette);if(hasCigarette){log.debug("可以干活了");}else{log.debug("没干成...");}}finally {ROOM.unlock();}},"小南").start();new Thread(()->{//1.拿到ReentrantLock锁资源ROOM.lock();try{log.debug("外卖送到没?[{}]",hasTakeOut);//2.防止虚假唤醒while(!hasTakeOut){log.debug("没外卖,先歇会!");try {//2.2进入休息室,释放锁资源waitTakeOutSet.await();} catch (InterruptedException e) {e.printStackTrace();}}log.debug("可以开始干活了");}finally {ROOM.unlock();}},"小女").start();/*** 唤醒线程*/sleep(1000);new Thread(()->{ROOM.lock();try{hasTakeOut=true;log.debug("开始送外卖了...");//叫醒waitTakeOutSet.signal();}finally {ROOM.unlock();}},"送外卖的").start();/*** 送烟线程,送完外卖1s后开始*/sleep(1000);new Thread(()->{ROOM.lock();try{hasCigarette=true;log.debug("开始送烟了...");waitCigaretteSet.signal();}finally {ROOM.unlock();}},"送烟的").start();}
}


总结:

临界区:对共享资源有匹操作;

synchronized的三种方法:方法上(static有无两种)+锁对象

synchronized解决临界区代码原子性;

同步方法我们可以用wait/notify:线程唤醒,线程阻塞

lock:

条件变量:可以并行多个线程;

互斥:利用Lock和synchronized保证共享资源互斥效果;

同步:利用wait,notify或Lock条件变量达到线程间通信效果;

Lock的条件变量就是利用Condition类创建Condition对象调用await和sinal方法将当前线程阻塞与唤醒;

原理:

 Monitor管城:1.互斥作用,保证临界区代码的原子性; 2.同步;

entryList:获取不到进入;

waitSet:条件不满足时进去

设计模式-一些输出方式demo相关推荐

  1. (C++)string 的两种输入方式和输出方式

    注:头文件如下 #include<string> #include<cstdio> #include<iostream>using namespace std; 注 ...

  2. 改造HINT的输出方式

    Delphi为每个可视构件(而非快速按钮专属)都提供了Hint及ShowHint特性,其中Hint属性指定文本提示盒中的文本,   而ShowHint属性则决定鼠标指向构件时是否显示文本提示盒,当Sh ...

  3. asp.net webform html,ASP.NET WebForm页面内容输出方式

    这次我们谈的话题是"Web Form页面上输出内容的方式".这其实是一个非常旧的话题了,因为本文的内容甚至可以运用于ASP.NET 1.1之上.不过这个话题的适用范围很广,因为即使 ...

  4. 单例设计模式介绍||单例设计模式八种方式——1) 饿汉式(静态常量) 2) 饿汉式(静态代码块) 3) 懒汉式(线程不安全) 4) 懒汉式(线程安全,同步方法)

    单例模式 单例设计模式介绍 所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法(静态方法). 比如Hibernate的 ...

  5. php 输出的区别,php的6种输出方式的区别_后端开发

    程序中的注释部分是否参加编译?_后端开发 程序中的注释部分是不参加编译的,也不会出现在目标程序中的,程序中的注释只是为了让程序员能更方便地读懂程序而提出来的,也就是说程序中的注释是给代码一个批注,让其 ...

  6. 十六进制的几种输出方式

    /*  time:2016.6.20  function:  aim:测试十六进制的不同输出方式,%x,%X,%#x,%#X; */ #include <stdio.h> #include ...

  7. 深度学习(21)神经网络与全连接层四: 输出方式

    深度学习(21)神经网络与全连接层四: 输出方式 1. y∈Rdy∈R^dy∈Rd 2. yi∈[0,1]y_i∈[0,1]yi​∈[0,1] 3. sigmoid函数 (1) 目的 (2) tf.s ...

  8. python读取mysql以html形式输出_python实现处理mysql结果输出方式

    在运维过程中,经常需要读取mysql的结果输出并进行响应的处理,这节介绍如何用Python读取mysql结果表并进行相应的整理. 进行mysql结果文件输出: mysql -h10.20.10.207 ...

  9. python清除输出内容_jupyter notebook清除输出方式

    在 jupyter notebook参数化运行python时,怕输出太多文件太大,想及时清除 notebook 的输出. 在别人代码里看到用 easydl 的 clear_output().调用很简单 ...

  10. (3)分布式下的爬虫Scrapy应该如何做-递归爬取方式,数据输出方式以及数据库链接...

    放假这段时间好好的思考了一下关于Scrapy的一些常用操作,主要解决了三个问题: 1.如何连续爬取 2.数据输出方式 3.数据库链接 一,如何连续爬取: 思考:要达到连续爬取,逻辑上无非从以下的方向着 ...

最新文章

  1. 5月17日 AJAX 之 XML
  2. 【LeetCode笔记】42. 接雨水(Java、动态规划)
  3. 主持人李咏在美国去世 妻子哈文:永失我爱
  4. 二十天一学通C#:.NET中文件和文件夹的类
  5. C语言函数的定义和声明
  6. Core的.mli文件在哪里
  7. vue使用高德地图web端JSAPI 路线规划、搜索提示教程
  8. 2020-12-22 ACM集训一(二维数组与结构体)
  9. 如何下载ArcGis Server离线地图瓦片数据
  10. $Loj10155$ 数字转换(求树的最长链) 树形$DP$
  11. bmob android博客,(android)bmob中实现保存
  12. 3D角色 毛发制作 XGen关于导向的基本操作
  13. 中资电信银行股将成市场旗手
  14. 解决ubuntu14 restart mysql提示stop Unknown job:mysql问题
  15. html百度站内搜索代码,百度站内搜索如何安装 百度站内搜索代码如何部署使用...
  16. android 2.2下载地址,Windows下载android2.2完整源码
  17. Python 最常见的 170 道面试题解析
  18. Fluent Wallet已登陆Edge与Chrome商店
  19. 用Python判断矩阵是否为可逆矩阵
  20. 秦韵FPGA 转载或原创(十四) 高云FPGAGW2A18C

热门文章

  1. FPGA开发板学习(1)
  2. 拳王虚拟项目公社:骚年,你想成为百年难遇的“地摊之王”吗?
  3. audio_policy_configuration.xml文件解析
  4. 玩游戏计算机丢失msvcp,计算机丢失msvcp怎么办
  5. IDEA告警:Field can be converted to a local varible
  6. 一文了解知识图谱能做什么、本文含Jiagu自然语言处理工具试用、知识图谱实战。
  7. 寒霜3引擎再造经典极品飞车18
  8. .net分流抢票助手
  9. 计算机网络应用层题库
  10. Angular:升级Angular 13到Angular 14