多執行緒協作demo
啟動兩個執行緒, 一個輸出1,3,5,7,9....99,另一個輸出2,4,6,8....100,最後在terminal中輸出1,2,3,4,5,6.....100
java 執行緒實現
/** * 多執行緒併發的時候需要通過一個鎖來進行wait和notify控制執行緒的喚醒和等待 */ Object lock = new Object(); /** * lambda程式碼塊只能操作lambda程式碼塊外的final變數,但是有時候又需要改變這個變數, * 所以通過final陣列來規避這個問題。 */ final Thread[] threads = new Thread[2]; /** * 當兩個列印執行緒結束之後main執行緒退出 */ CountDownLatch countDownLatch = new CountDownLatch(2); threads[1] = new Thread(() -> { for (int i = 2; i <= 100; i += 2) { System.out.println(i); /** * wait, notify, notifyAll 等方法需要在同步程式碼塊中執行以保證併發安全。 */ synchronized (lock) { try { /** *喚醒thread[0] */ lock.notifyAll(); if (i != 100) { /** * 本執行緒進入等待狀態,釋放cpu */ lock.wait(); } } catch (InterruptedException e) { e.printStackTrace(); } } } countDownLatch.countDown(); }); threads[0] = new Thread(() -> { for (int i = 1; i < 100; i += 2) { System.out.println(i); synchronized (lock) { try { /** * 當i==1時代表thread[1]尚未開始啟動 * 當i!=1時喚醒thread[1] * 然後本執行緒進入等待狀態釋放cpu */ if (i == 1) { threads[1].start(); } else { lock.notifyAll(); } if (i != 99) { lock.wait(); } } catch (InterruptedException e) { e.printStackTrace(); } } } countDownLatch.countDown(); }); /** * 啟動thread[0] */ threads[0].start(); /** * main執行緒進入等待狀態,當thread[0]和thread[1]的任務執行完成之後main執行緒被喚醒 */ countDownLatch.await(); System.out.println("兩個執行緒通過notify和wait實現迴圈列印100以內的數");
golang 協程實現
協程是使用者級別的執行緒。在java中程式排程的基本單位是執行緒,java的執行緒和作業系統的執行緒是一一對應的,執行緒的排程是由作業系統核心完成的。golang中提供了協程來實現併發,多個協程執行在一個作業系統的執行緒上,協程的排程由使用者態程式碼來實現,因而協程式更加輕量級。
a := make(chan bool, 1) b := make(chan bool) Exit := make(chan bool) //<- chan 當chan中沒有資料時會阻塞 //a <- true 往chan a 中放入放入一個值,此時阻塞的協程開始執行 //go func 啟動一個協程 go func() { for i := 1; i < 100; i += 2 { if ok := <-a; ok { fmt.Println(i) b <- true } } }() go func() { for i := 2; i <= 100; i += 2 { if ok := <-b; ok { fmt.Println(i) a <- true } } // 迴圈列印結束,主協程退出 close(Exit) }() fmt.Println("end") a <- true _ := <-Exit