【Java併發編程學習】三、線程掛起、恢復和終止

/**
 * 經過休眠來延緩運行,模擬長時間運行的狀況,使線程更可能在不適當的時候被掛起
 * 說明:若是在不合適的時候掛起線程(如鎖定共享資源時),此時即可能會發生死鎖條件--其它線程在等待該線程釋放鎖,
 * 但該線程卻被掛起,便會發生死鎖。
 */
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()方法,能夠忽然終止線程,可是它可能致使數據對象崩潰。
相關文章
相關標籤/搜索