java多執行緒輪流列印資料問題
阿新 • • 發佈:2019-02-09
題目是:
建立三個執行緒,A執行緒列印10次A,B執行緒列印10次B,C執行緒列印10次C,要求執行緒同時執行,交替列印10次ABC
理解:
Obj.wait(),與Obj.notify()必須要與synchronized(Obj)一起使用,也就是wait,與notify是針對已經獲取了Obj鎖進行操作,從語法角度來說就是Obj.wait(),Obj.notify必須在synchronized(Obj){...}語句塊內。從功能上來說wait就是說執行緒在獲取物件鎖後,主動釋放物件鎖,同時本執行緒休眠。直到有其它執行緒呼叫物件的notify()喚醒該執行緒,才能繼續獲取物件鎖,並繼續執行。相應的notify()就是對物件鎖的喚醒操作。但有一點需要注意的是notify()呼叫後,並不是馬上就釋放物件鎖的,而是在相應的synchronized(){}語句塊執行結束,自動釋放鎖後,JVM會在wait()物件鎖的執行緒中隨機選取一執行緒,賦予其物件鎖,喚醒執行緒,繼續執行。這樣就提供了線上程間同步、喚醒的操作。Thread.sleep()與Object.wait()二者都可以暫停當前執行緒,釋放CPU控制權,主要的區別在於Object.wait()在釋放CPU同時,釋放了物件鎖的控制。程式碼實現是:
public class PrintRunnable implements Runnable { private int count = 10; private String name; private Object pre; private Object own; public PrintRunnable(String name,Object pre,Object own) { this.name = name; this.pre = pre; this.own = own; } @Override public void run() { while(count > 0){ synchronized (pre) { synchronized (own) { System.out.print(name); count--; own.notify(); } try { pre.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } }
測試程式碼是:
public class MainTest { public static void main(String[] args) throws InterruptedException { Object a = new Object(); Object b = new Object(); Object c = new Object(); Thread t1 = new Thread(new PrintRunnable("A", c, a)); Thread t2 = new Thread(new PrintRunnable("B", a, b)); Thread t3 = new Thread(new PrintRunnable("C", b, c)); t1.start(); Thread.sleep(100); t2.start(); Thread.sleep(100); t3.start(); Thread.sleep(100); } }
測試結果:
ABCABCABCABCABCABCABCABCABCABC
分析:
首先啟動第一個執行緒,列印一個A,喚醒A鎖,count--,(c.wait():釋放C鎖,第一個執行緒在迴圈中等待)。
其次啟動第二個執行緒,列印一個B,喚醒B鎖,count--,(a.wait():釋放A鎖,第二個執行緒在迴圈中等待)。
最後啟動第三個執行緒,列印一個C,喚醒C鎖,count--,(b.wait():釋放B鎖,第三個執行緒在迴圈中等待)。
由於第三個執行緒在迴圈中喚醒C鎖,其執行完之後,會喚醒持有C鎖等待的第一個執行緒,然後第一個執行緒執行完之後再喚醒迴圈中持有B鎖的第二個執行緒,同理,依次執行喚醒操作。