這是一道考察多線程的題目。應題目的要求,子線程循環10次和主線程循環100次的中途不能被打斷,則須要在循環方法裏面加入互斥鎖。要連續有規律運行主線程和子線程,能夠考慮當線程執行完一個週期的循環後,讓線程休眠讓出線程運行權,或者使用wita()和notify()方法。java
public class TranditionThreadCommunication { public static void main(String[] args) { final Business business = new Business(); // 子線程循環 new Thread(new Runnable() { @Override public void run() { for (int i = 1; i <= 50; i++) { try { business.sub(i); } catch (InterruptedException e) { } } } }).start(); // 主線程循環 for (int i = 1; i <= 50; i++) { try { business.mian(i); } catch (InterruptedException e) { } } } } /** * 業務類型(包含各色的同步鎖) */ class Business { // sub()方法是否該運行標識 private boolean bShouldSub = true; /** * 循環100次打印的方法sub() * * @param i * @throws InterruptedException */ public synchronized void sub(int i) throws InterruptedException { while (!bShouldSub) { // 當 bShouldSub 爲 false 時,則等待 this.wait(); } for (int j = 1; j <= 10; j++) { System.out.println("sub thread : 第" + i + "行, 第" + j + "列"); } bShouldSub = false; // 執行for循環後,標誌sub()方法不可再執行 this.notify(); // 喚醒線程 } /** * 循環100次打印的方法mian() * * @param i * @throws InterruptedException */ public synchronized void mian(int i) throws InterruptedException { while (bShouldSub) { this.wait(); } for (int j = 1; j <= 100; j++) { System.out.println("main thread : 第" + i + "行, 第" + j + "列"); } bShouldSub = true; // 執行for循環後,標誌sub()方法可再執行了 this.notify(); // 喚醒線程 } }
(1)要用到共同數據(包括同步鎖)或共同算法的若干個方法應該歸在同一個類身上,這種設計體現了高類聚和程序的健壯性。像上面的循環10次和循環100次的操做都須要用到鎖時,能夠將這兩個方法加上鎖(synchronized)並放到Business類中。算法
(2)上面答案中的多線程
while (bShouldSub) { this.wait(); }
借鑑了javaAPI 中的wait()方法的寫法,主要是爲了防止線程之間可能出現的僞喚醒。app
java API 中的wait()方法的原文以下:ide
public final void wait() throws InterruptedException 在其餘線程調用此對象的 notify() 方法或 notifyAll() 方法前,致使當前線程等待。換句話說,此方法的行爲就好像它僅執行 wait(0) 調用同樣。 當前線程必須擁有此對象監視器。該線程發佈對此監視器的全部權並等待,直到其餘線程經過調用 notify 方法,或 notifyAll 方法通知在此對象的監視器上等待的線程醒來。而後該線程將等到從新得到對監視器的全部權後才能繼續執行。this
對於某一個參數的版本,實現中斷和虛假喚醒是可能的,並且此方法應始終在循環中使用:線程
synchronized (obj) { while (<condition does not hold>) obj.wait(); // Perform action appropriate to condition }
此方法只應由做爲此對象監視器的全部者的線程來調用。有關線程可以成爲監視器全部者的方法的描述,請參閱 notify 方法。 拋出: IllegalMonitorStateException - 若是當前線程不是此對象監視器的全部者。 InterruptedException - 若是在當前線程等待通知以前或者正在等待通知時,任何線程中斷了當前線程。在拋出此異常時,當前線程的中斷狀態 被清除。設計