/** * 經過休眠來延緩運行,模擬長時間運行的狀況,使線程更可能在不適當的時候被掛起 * 說明:若是在不合適的時候掛起線程(如鎖定共享資源時),此時即可能會發生死鎖條件--其它線程在等待該線程釋放鎖, * 但該線程卻被掛起,便會發生死鎖。 */ public class DeprecatedSuspendResume extends Object implements Runnable{ private volatile int firstVal; private volatile int secondVal; public boolean areValuesEqual() { return (firstVal == secondVal); } @Override public void run() { try { firstVal = 0; secondVal = 0; workMethod(); } catch (InterruptedException e) { System.out.println("[DeprecatedSuspendResume] interrupted while in workMethod()"); } } private void workMethod() throws InterruptedException { int val = 1; while (true) { /** * 若設置firstVal以後,但在設置secondVal以前,掛起新線程會產生麻煩 */ stepOne(val); stepTwo(val); val++; // 再次循環前休眠200 ms Thread.sleep(200); } } /** * 賦值後,休眠300ms,從而使線程有機會在stepOne()和stepTwo()之間被掛起 */ private void stepOne(int newVal) throws InterruptedException { firstVal = newVal; // 模擬長時間運行的狀況 Thread.sleep(300); } private void stepTwo(int newVal) { secondVal = newVal; } public static void main(String[] args) { DeprecatedSuspendResume dsr = new DeprecatedSuspendResume(); Thread thread = new Thread(dsr); thread.start(); // 休眠1 s,讓其它線程有機會得到執行 try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } for (int i = 0; i < 10; i++) { // 掛起線程 thread.suspend(); System.out.println("[DeprecatedSuspendResume] dsr.areValuesEqual() = " + dsr.areValuesEqual() + " [main]= " + Thread.currentThread().getId() + " [thread]=" + thread.getId()); // 恢復線程 thread.resume(); try { // 線程隨機休眠0~2 s Thread.sleep((long)(Math.random()*2000.0)); } catch (InterruptedException e) { } } // 中斷應用程序 System.exit(0); } }
/** * 實現線程掛起和恢復的策略--設置標誌位,能夠在線程的指定位置實現線程的掛起和恢復,而不用擔憂其不肯定性。 */ public class AlternateSuspendResume extends Object implements Runnable { private volatile int firstVal; private volatile int secondVal; /** * 增長標誌位,用來實現線程的掛起和恢復 */ private volatile boolean suspended; public boolean areValuesEqual() { return (firstVal == secondVal); } @Override public void run() { try { suspended = false; firstVal = 0; secondVal = 0; workMethod(); } catch (InterruptedException e) { System.out.println("[AlternateSuspendResume] interrupted while in workMethod()"); } } private void workMethod() throws InterruptedException { int val = 1; while (true) { // 僅當線程掛起時,才運行這行代碼 waitWhileSuspended(); stepOne(val); stepTwo(val); val++; // 僅當線程掛起時,才運行這行代碼 waitWhileSuspended(); Thread.sleep(200); } } private void stepOne(int newVal) throws InterruptedException { firstVal = newVal; Thread.sleep(300); } private void stepTwo(int newVal) { secondVal = newVal; } public void suspendRequest() { suspended = true; } public void resumeRequest() { suspended = false; } private void waitWhileSuspended() throws InterruptedException { // 這是一個「繁忙等待」技術的示例 while (suspended) { Thread.sleep(200); } } public static void main(String[] args) { AlternateSuspendResume asr = new AlternateSuspendResume(); Thread thread = new Thread(asr); thread.start(); // 休眠1 s,讓其它線程有機會得到執行 try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } /** * 設置firstVal以後,但在設置secondVal以前,掛起新線程 * 此處休眠目的是爲了防止在執行asr.areValuesEqual()進行比較時, * 恰逢stepOne操做執行完,而stepTwo操做還沒執行 */ try { Thread.sleep(350); } catch (InterruptedException e) { e.printStackTrace(); } for (int i = 0; i < 10; i++) { asr.suspendRequest(); System.out.println("[AlternateSuspendResume] asr.areValuesEqual()= " + asr.areValuesEqual() + "[main]= " + Thread.currentThread().getId() + "[thread]= " + thread.getId()); asr.resumeRequest(); } try { // 線程隨機休眠0~2 s Thread.sleep((long)(Math.random() * 2000.0)); } catch (InterruptedException e) { e.printStackTrace(); } // 退出應用程序 System.exit(0); } }
* 終止線程:當調用Thread的start()方法,執行完run()方法後,或在run()方法中return,線程便會天然消亡。 * 注:Thread API中包含了一個stop()方法,能夠忽然終止線程,可是它可能致使數據對象崩潰。