Java三個執行緒迴圈列印
阿新 • • 發佈:2018-12-10
先上效果圖:
目錄
資源
這裡用了condition
執行流程:執行緒1執行完,讓執行緒2醒來工作;執行緒2執行完,讓執行緒3醒來工作;執行緒3執行完,讓執行緒1醒來工作
原理(都是按最壞的情況分析):
①一開始3個執行緒搶鎖,如果執行緒2和3搶到鎖,會進入等待(因為num=1),並釋放鎖,此時只有執行緒1可以拿鎖
②執行緒1開始執行,將num=2,並喚醒執行緒2,此時執行緒1和執行緒2競爭鎖,如果執行緒1搶到鎖,會進入等待,並釋放鎖,此時只有執行緒2可以拿鎖
③執行緒2開始執行,將num=3,並喚醒執行緒3,此時執行緒2和執行緒3競爭鎖,如果執行緒2搶到鎖,會進入等待,並釋放鎖,此時只有執行緒3
④執行緒3開始執行,將num=1,並喚醒執行緒1,此時執行緒3和執行緒1競爭鎖,如果執行緒3搶到鎖,會進入等待,並釋放鎖,此時只有執行緒1可以拿鎖
這樣就能保證三個執行緒迴圈執行了
import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class Resource { //num=1就是執行緒1執行,num=2就是執行緒2執行,num=3就是執行緒3執行 private int num = 1; private Lock lock = new ReentrantLock();//建立鎖物件 private Condition condition1 = lock.newCondition();//條件1 private Condition condition2 = lock.newCondition();//條件2 private Condition condition3 = lock.newCondition();//條件3 public void sub1() { try { lock.lock();//開啟鎖 while (num != 1){//這裡jdk原始碼裡推薦用while,因為有可能出現虛假喚醒,所以要再次確認 try { condition1.await();//條件1執行緒等待,並釋放鎖 } catch (InterruptedException e) { e.printStackTrace(); } } //執行到這裡,說明num=1 num=2; Thread.sleep(1000); System.out.println("執行緒1執行完畢"); condition2.signal();//喚醒條件2執行緒 } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock();//釋放鎖 } } public void sub2() { try { lock.lock();//開啟鎖 while (num !=2) {//這裡jdk原始碼裡推薦用while,因為有可能出現虛假喚醒,所以要再次確認 try { condition2.await();//條件2執行緒等待,並釋放鎖 } catch (InterruptedException e) { e.printStackTrace(); } } //如果執行緒執行到這裡,說明num=2 num=3; Thread.sleep(1000); System.out.println("執行緒2執行完畢"); condition3.signal();//喚醒條件3執行緒 } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock();//釋放鎖 } } public void sub3() { try { lock.lock();//開啟鎖 while (num !=3) {//這裡jdk原始碼裡推薦用while,因為有可能出現虛假喚醒,所以要再次確認 try { condition3.await();//條件3執行緒等待,並釋放鎖 } catch (InterruptedException e) { e.printStackTrace(); } } //如果執行緒執行到這裡,說明num=3 num=1; Thread.sleep(1000); System.out.println("執行緒3執行完畢"); condition1.signal();//喚醒條件1執行緒 } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock();//釋放鎖 } } }
測試
public static void main(String[] args) { Resource resource = new Resource(); //第一個執行緒 new Thread(new Runnable() { @Override public void run() { while (true) { resource.sub1(); } } }).start(); //第二個執行緒 new Thread(new Runnable() { @Override public void run() { while (true) { resource.sub2(); } } }).start(); //第三個執行緒 new Thread(new Runnable() { @Override public void run() { while (true) { resource.sub3(); } } }).start(); }