實現手機直播原始碼中兩個執行緒依次執行的相關程式碼
雖然通常在手機直播原始碼中每個子執行緒只需要完成自己的任務,但是有時我們希望多個執行緒一起工作來完成一個任務,這就涉及到執行緒間通訊。今天我們主要來了解一下實現手機直播原始碼中兩個執行緒依次執行的相關程式碼。
假設手機直播原始碼中有兩個執行緒:A 和 B,這兩個執行緒都可以按照順序列印數字,程式碼如下:
public class Test01 { public static void main(String[] args) throws InterruptedException { demo1(); } public static void demo1() { Thread a = new Thread(() -> { printNumber("A"); }); Thread b = new Thread(() -> { printNumber("B"); }); a.start(); b.start(); } public static void printNumber(String threadName) { int i = 0; while (i++ < 3) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(threadName + " print: " + i); } } }
得到的結果如下:
A print: 1 B print: 1 B print: 2 A print: 2 A print: 3 B print: 3
可以看到 A 和 B 同時列印數字,如果我們希望 B 在 A 執行完成之後開始執行,那麼可以使用 thread.join() 方法實現,程式碼如下:
public static void demo2() { Thread a = new Thread(() -> { printNumber("A"); }); Thread b = new Thread(() -> { System.out.println("B 等待 A 執行"); try { a.join(); } catch (InterruptedException e) { e.printStackTrace(); } printNumber("B"); }); a.start(); b.start(); }
得到的結果如下:
B 等待 A 執行 A print: 1 A print: 2 A print: 3 B print: 1 B print: 2 B print: 3
我們可以看到該 a.join() 方法會讓 B 等待 A 完成列印。
thread.join() 方法的作用就是阻塞當前執行緒,等待呼叫 join() 方法的執行緒執行完畢後再執行後面的程式碼。
檢視 join() 方法的原始碼,內部是呼叫了 join(0) ,如下:
public final void join() throws InterruptedException { join(0); }
檢視 join(0) 的原始碼如下:
// 注意這裡使用了 sychronized 加鎖,鎖物件是執行緒的例項物件 public final synchronized void join(long millis) throws InterruptedException { long base = System.currentTimeMillis(); long now = 0; if (millis < 0) { throw new IllegalArgumentException("timeout value is negative"); } // 呼叫 join(0) 執行下面的程式碼 if (millis == 0) { // 這裡使用 while 迴圈的目的是為了避免虛假喚醒 // 如果當前執行緒存活則呼叫 wait(0), 0 表示永久等待,直到呼叫 notifyAll() 或者 notify() 方法 // 當執行緒結束的時候會呼叫 notifyAll() 方法 while (isAlive()) { wait(0); } } else { while (isAlive()) { long delay = millis - now; if (delay <= 0) { break; } wait(delay); now = System.currentTimeMillis() - base; } } }
從原始碼中可以看出 join(long millis) 方法是通過 wait(long timeout) (Object 提供的方法)方法實現的,呼叫 wait 方法之前,手機直播原始碼當前執行緒必須獲得物件的鎖,所以此 join 方法使用了 synchronized 加鎖,鎖物件是執行緒的例項物件。
其中 wait(0)方法會讓當前執行緒阻塞等待,直到另一個執行緒呼叫此物件的 notify() 或者 notifyAll() 方法才會繼續執行。當呼叫 join 方法的執行緒結束的時候會呼叫 notifyAll() 方法,所以 join() 方法可以實現手機直播原始碼中一個執行緒等待另一個呼叫 join() 的執行緒結束後再執行。
虛假喚醒:一個執行緒在沒有被通知、中斷、超時的情況下被喚醒;
虛假喚醒可能導致條件不成立的情況下手機直播原始碼執行程式碼,破壞被鎖保護的約束關係;
為什麼使用 while 迴圈來避免虛假喚醒:
在 if 塊中使用 wait 方法,是非常危險的,因為一旦手機直播原始碼中的執行緒被喚醒,並得到鎖,就不會再判斷 if 條件而執行 if 語句塊外的程式碼,所以建議凡是先要做條件判斷,再 wait 的地方,都使用 while 迴圈來做,迴圈會在等待之前和之後對條件進行測試。
本文轉載自網路,轉載僅為分享乾貨知識,如有侵權歡迎聯絡雲豹科技進行刪除處理
原文連結:
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69996194/viewspace-2848343/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 執行緒池的實現程式碼分析執行緒
- 執行緒(一)——執行緒,執行緒池,Task概念+程式碼實踐執行緒
- 執行緒池執行模型原始碼全解析執行緒模型原始碼
- 語音社交原始碼開發,兩個執行緒按照指定方式有序相交的實現原始碼執行緒
- 直播商城原始碼,android執行緒的介紹及兩種啟動方式原始碼Android執行緒
- 執行緒中的幾個退出相關函式執行緒函式
- 執行緒池原始碼探究執行緒原始碼
- 執行緒池原始碼分析執行緒原始碼
- 多執行緒程式設計-分析阻塞佇列的原始碼實現執行緒程式設計佇列原始碼
- 關於多執行緒的兩種實現方式執行緒
- 從原始碼的角度解析執行緒池執行原理原始碼執行緒
- 執行緒池相關執行緒
- 多執行緒的執行緒狀態及相關操作執行緒
- 約玩原始碼中執行緒的呈現狀態,死鎖程式碼如何寫?原始碼執行緒
- 執行緒池的實現原始碼及應用舉例執行緒原始碼
- 深入原始碼,深度解析Java 執行緒池的實現原理原始碼Java執行緒
- 執行緒池之ScheduledThreadPoolExecutor執行緒池原始碼分析筆記執行緒thread原始碼筆記
- 執行緒池之ThreadPoolExecutor執行緒池原始碼分析筆記執行緒thread原始碼筆記
- 併發程式設計之 原始碼剖析 執行緒池 實現原理程式設計原始碼執行緒
- 155 執行緒的相關操作執行緒
- JDK執行緒池原始碼研究JDK執行緒原始碼
- 多執行緒程式是如何執行程式碼的?執行緒行程
- ConcurrentHashMap執行緒安全機制以及原始碼分析HashMap執行緒原始碼
- 執行緒池的建立和使用,執行緒池原始碼初探(篇一)執行緒原始碼
- 多執行緒相關整理執行緒
- 原始碼|從序列執行緒封閉到物件池、執行緒池原始碼執行緒物件
- Netty原始碼解析一——執行緒池模型之執行緒池NioEventLoopGroupNetty原始碼執行緒模型OOP
- 編碼:執行緒執行監控執行緒
- OpenMP 執行緒同步 Construct 實現原理以及原始碼分析(上)執行緒Struct原始碼
- OpenMP 執行緒同步 Construct 實現原理以及原始碼分析(下)執行緒Struct原始碼
- 1v1影片原始碼,你知道如何實現多執行緒的順序執行嗎?原始碼執行緒
- ScheduledThreadPoolExecutor原始碼分析-你知道定時執行緒池是如何實現延遲執行和週期執行的嗎?thread原始碼執行緒
- 執行緒、開啟執行緒的兩種方式、執行緒下的Join方法、守護執行緒執行緒
- python多執行緒中:如何關閉執行緒?Python執行緒
- Java原始碼解析 ThreadPoolExecutor 執行緒池Java原始碼thread執行緒
- Java原始碼解析 - ThreadPoolExecutor 執行緒池Java原始碼thread執行緒
- Java執行緒池ThreadPoolExecutor原始碼解析Java執行緒thread原始碼
- Python執行緒池ThreadPoolExecutor原始碼分析Python執行緒thread原始碼