java並發編程(三)線程掛起,恢復和終止的正確方法


轉載請注明出處:http://blog.csdn.net/ns_code/article/details/17095733

   下面我們給出不用上述兩個方法來實現線程掛起和恢復的策略——設置標志位。通過該方法實現線程的掛起和恢復有一個很好的地方,就是可以在線程的指定位置實現線程的掛起和恢復,而不用擔心其不確定性。 

 

package com.wenjie;

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 );  
    }  
  
    public void run() {  
        try {  
            suspended = false;  
            firstVal = 0;  
            secondVal = 0;  
            workMethod();  
        } catch ( InterruptedException x ) {  
            System.out.println("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 {  
  
        //這是一個“繁忙等待”技術的示例。  
        //它是非等待條件改變的最佳途徑,因為它會不斷請求處理器周期地執行檢查,   
        //更佳的技術是:使用Java的內置“通知-等待”機制  
        while ( suspended ) {  
            Thread.sleep(200);  
        }  
    }  
  
    public static void main(String[] args) {  
        AlternateSuspendResume asr =   
                new AlternateSuspendResume();  
  
        Thread t = new Thread(asr);  
        t.start();  
  
        //休眠1秒,讓其他線程有機會獲得執行  
        try { Thread.sleep(1000); }   
        catch ( InterruptedException x ) { }  
  
        for ( int i = 0; i < 10; i++ ) {  
            asr.suspendRequest();  
  
            //讓線程有機會注意到掛起請求  
            //注意:這里休眠時間一定要大於  
            //stepOne操作對firstVal賦值后的休眠時間,即300ms,  
            //目的是為了防止在執行asr.areValuesEqual()進行比較時,  
            //恰逢stepOne操作執行完,而stepTwo操作還沒執行  
            try { Thread.sleep(350); }   
            catch ( InterruptedException x ) { }  
  
            System.out.println("dsr.areValuesEqual()=" +   
                    asr.areValuesEqual());  
  
            asr.resumeRequest();  
  
            try {   
                //線程隨機休眠0~2秒  
                Thread.sleep(  
                        ( long ) (Math.random() * 2000.0) );  
            } catch ( InterruptedException x ) {  
                //
            }  
        }  
  
        System.exit(0); //退出應用程序  
    }  
}  

 

結果

dsr.areValuesEqual()=true
dsr.areValuesEqual()=true
dsr.areValuesEqual()=true
dsr.areValuesEqual()=true
dsr.areValuesEqual()=true
dsr.areValuesEqual()=true
dsr.areValuesEqual()=true
dsr.areValuesEqual()=true
dsr.areValuesEqual()=true
dsr.areValuesEqual()=true

    1.線程掛起的位置不確定  這里確定了線程掛起的位置,不會出現線程在stepOne操作和stepTwo操作之間掛起的情況;針對情況2main線程中執行asr.areValuesEqual()進行比較時,恰逢stepOne操作執行完,而stepTwo操作還沒執行asr.areValuesEqual()操作前,讓main線程休眠450ms(>300ms),如果掛起請求發出時,新線程正執行到或即將執行到stepOne操作(如果在其前面的話,就會響應掛起請求,從而掛起線程),那么在stepTwo操作執行前,main線程的休眠還沒結束,從而main線程休眠結束后執行asr.areValuesEqual()操作進行比較時,stepTwo操作已經執行完,因此也不會出現輸出結果為false的情況。

總結:線程的掛起和恢復實現的正確方法是:通過設置標志位,讓線程在安全的位置掛起

 

終止線程

 

   當調用Thread的start()方法,執行完run()方法后,或在run()方法中return,線程便會自然消亡。另外Thread API中包含了一個stop()方法,可以突然終止線程。但它在JDK1.2后便被淘汰了,因為它可能導致數據對象的崩潰。一個問題是,當線程終止時,很少有機會執行清理工作;另一個問題是,當在某個線程上調用stop()方法時,線程釋放它當前持有的所有鎖,持有這些鎖必定有某種合適的理由——也許是阻止其他線程訪問尚未處於一致性狀態的數據,突然釋放鎖可能使某些對象中的數據處於不一致狀態,而且不會出現數據可能崩潰的任何警告

當調用Thread的start()方法,執行完run()方法后,或在run()方法中return,線程便會自然消亡。另外Thread API中包含了一個stop()方法,可以突然終止線程。但它在JDK1.2后便被淘汰了,因為它可能導致數據對象的崩潰。一個問題是,當線程終止時,很少有機會執行清理工作;另一個問題是,當在某個線程上調用stop()方法時,線程釋放它當前持有的所有鎖,持有這些鎖必定有某種合適的理由——也許是阻止其他線程訪問尚未處於一致性狀態的數據,突然釋放鎖可能使某些對象中的數據處於不一致狀態,而且不會出現數據可能崩潰的任何警告。

終止線程的替代方法:同樣是使用標志位,通過控制標志位來終止線程。

 


 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM