用三個執行緒按順序迴圈列印abc 三個字母,比如abcabcabc
阿新 • • 發佈:2019-01-06
執行緒類
main函式
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; /** * Created by Andrew on 2017/3/22. */ public class PrintThread implements Runnable{ private String symbol; private Condition conditionA =null; private int go = 0; private ReentrantLock lock =null; //使用原子類,本例中並沒有多大意義 private static AtomicInteger i=new AtomicInteger(0); public PrintThread(String symbol, Condition conditionA,int go,ReentrantLock lock) { this.symbol = symbol; this.lock = lock; this.conditionA = conditionA; this.go = go; } @Override public void run() { while (true){ lock.lock(); try { while (i.get() % 3 != go) { conditionA.await(); } } catch (InterruptedException e) { e.printStackTrace(); } //防止過多輸出 if (i.get()==10)break; System.out.println("result "+symbol); i.getAndIncrement(); // System.out.println(i.get()); //可以試試signalAll或signal區別,比較時建議去掉前面的break conditionA.signalAll(); lock.unlock(); } } }
main函式
import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; /** * Created by Andrew on 2017/3/22. */ public class PrintLetter { private static ReentrantLock lock = new ReentrantLock(); private static Condition conditionA = lock.newCondition(); public static void main(String[] args) throws InterruptedException { new Thread(new PrintThread("A",conditionA,0,lock)).start(); new Thread(new PrintThread("B",conditionA,1,lock)).start(); new Thread(new PrintThread("C",conditionA,2,lock)).start(); } }
下面這種實現是我最初的想法但當時並沒能實現,這種方式我認為比較巧妙但存在兩大問題:
1.達到目的後仍有執行緒處於等待狀態。
2.由於執行環境可能達不到最終結果。主要原因是執行緒排程順序
錯誤排程順序:如果主執行緒在啟動A後,執行A,過程中又切回主執行緒,啟動了ThreadB,ThreadC,之後,由於A執行緒尚未釋放self.notify,也就是B需要在synchronized(prev)處等待,而這時C卻呼叫synchronized(prev)獲取了對b的物件鎖。這樣,在A呼叫完後,同時ThreadB獲取了prev也就是a的物件鎖,ThreadC的執行條件就已經滿足了,會列印C,之後釋放c,及b的物件鎖,這時ThreadB具備了執行條件,會列印B,也就是迴圈變成了ACBACB了/** * Created by Andrew on 2017/3/26. */ public class MyThreadPrinter implements Runnable { private String name; private Object prev; private Object self; private MyThreadPrinter(String name, Object prev, Object self) { this.name = name; this.prev = prev; this.self = self; } @Override public void run() { int count = 10; while (count > 0) { synchronized (prev) { synchronized (self) { System.out.print(name); count--; self.notify(); } try { prev.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } } public static void main(String[] args) throws Exception { Object a = new Object(); Object b = new Object(); Object c = new Object(); MyThreadPrinter pa = new MyThreadPrinter("A", c, a); MyThreadPrinter pb = new MyThreadPrinter("B", a, b); MyThreadPrinter pc = new MyThreadPrinter("C", b, c); new Thread(pa).start(); new Thread(pb).start(); new Thread(pc).start(); } }