设计模式-一些输出方式demo
生活随笔
收集整理的這篇文章主要介紹了
设计模式-一些输出方式demo
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
?
目錄
例題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的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 实例学习之仿点点博客
- 下一篇: ims应用服务器,IMS应用