1. 程式人生 > >java三執行緒迴圈有序列印ABC

java三執行緒迴圈有序列印ABC

迅雷筆試題:

編寫一個程式,開啟 3個執行緒,這 3個執行緒的 ID分別為 A、 B、 C,每個執行緒將自己的 ID在螢幕上列印 10遍,要求輸出結果必須按 ABC的順序顯示;如: ABCABC….依次遞推。

解決思路:每個執行緒執行時先檢查他依賴的執行緒是否已完成工作,執行緒B依賴執行緒A的完成,執行緒C依賴執行緒B和執行緒A的完成,執行緒A依賴執行緒C的完成。如果當前執行緒依賴的執行緒沒有執行完,則阻塞當前執行緒直到條件滿足再執行。

Condition.await()會使當前執行緒暫時阻塞,並釋放ReentrantLock鎖.

Condition .signalAll()會通知啟用 Condition.await()而阻塞的執行緒,這時被啟用的執行緒就會繼續檢查(通過while迴圈))是否滿足條件,如果滿足而且再次獲得ReentrantLock鎖就能繼續執行,否則繼續等待。

 1 import java.util.concurrent.locks.Condition;
 2 import java.util.concurrent.locks.ReentrantLock;
 3 
 4 public class ThreadDemo implements Runnable {
 5 
 6     private ReentrantLock lock = new ReentrantLock();
 7     private Condition condition = lock.newCondition();
 8     //標記執行緒A的狀態,true為剛執行完。為什麼要兩個變數?因為只使用一個變數,當執行緒A執行完後,a為true,B執行緒就會不停執行
9 //所以執行緒B執行要執行必須滿足a==true&&a2==true 10 private volatile Boolean a = false, a2 = false; 11 //標記執行緒B的狀態,true為剛執行完。 12 private volatile Boolean b = false; 13 //標記執行緒C的狀態,true為剛執行完。 14 private volatile Boolean c = true; 15 16 @Override 17 public void run() { 18 String name = Thread.currentThread().getName(); 19
lock.lock(); 20 //進入臨界區 21 try { 22 for (int i = 0; i < 10; i++) { 23 if (name.equals("B")) { 24 //只有a和a2同時為true時才打印B,否則阻塞當前執行緒 25 while (!a || !a2) { 26 condition.await();//條件不滿足,暫時阻塞執行緒,暫時釋放lock 27 } 28 b = true; 29 a2 = false; 30 } else if (name.equals("C")) { 31 while (!a || !b) { 32 condition.await(); 33 } 34 c = true; 35 b = false; 36 } else if (name.equals("A")) { 37 while (!c) { 38 condition.await(); 39 } 40 a = true; 41 a2 = true; 42 b = false; 43 c = false; 44 } 45 System.out.print(name); 46 condition.signalAll();//通知正在等待的執行緒,此時有可能已經滿足條件 47 } 48 } catch (InterruptedException e) { 49 e.printStackTrace(); 50 } finally { 51 lock.unlock();// 記得要釋放鎖 52 } 53 } 54 55 public static void main(String[] args) throws InterruptedException { 56 ThreadDemo task = new ThreadDemo(); 57 Thread thread1 = new Thread(task); 58 Thread thread2 = new Thread(task); 59 Thread thread3 = new Thread(task); 60 thread1.setName("A"); 61 thread2.setName("B"); 62 thread3.setName("C"); 63 thread1.start(); 64 thread2.start(); 65 thread3.start(); 66 } 67 68 }