熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java高級技術 >> 正文

Java多線程初學者指南(4):線程的生命周期

2022-06-13   來源: Java高級技術 

  與人有生老病死一樣線程也同樣要經歷開始(等待)運行掛起和停止四種不同的狀態這四種狀態都可以通過Thread類中的方法進行控制下面給出了Thread類中和這四種狀態相關的方法

       // 開始線程
    public void start( );
    public void run( );

    // 掛起和喚醒線程
    public void resume( );     // 不建議使用
    public void suspend( );    // 不建議使用
    public static void sleep(long millis);
    public static void sleep(long millis int nanos);

    // 終止線程
    public void stop( );       // 不建議使用
    public void interrupt( );

    // 得到線程狀態
    public boolean isAlive( );
    public boolean isInterrupted( );
    public static boolean interrupted( );

    // join方法
    public void join( ) throws InterruptedException;

  創建並運行線程

  線程在建立後並不馬上執行run方法中的代碼而是處於等待狀態線程處於等待狀態時可以通過Thread類的方法來設置線程不各種屬性如線程的優先級(setPriority)線程名(setName)和線程的類型(setDaemon)等

  當調用start方法後線程開始執行run方法中的代碼線程進入運行狀態可以通過Thread類的isAlive方法來判斷線程是否處於運行狀態當線程處於運行狀態時isAlive返回true當isAlive返回false時可能線程處於等待狀態也可能處於停止狀態下面的代碼演示了線程的創建運行和停止三個狀態之間的切換並輸出了相應的isAlive返回值

   package chapter;

public class LifeCycle extends Thread
{
    public void run()
    {
        int n = ;
        while ((++n) < );        
    }
     
    public static void main(String[] args) throws Exception
    {
        LifeCycle thread = new LifeCycle();
        Systemoutprintln(isAlive:  + threadisAlive());
        threadstart();
        Systemoutprintln(isAlive:  + threadisAlive());
        threadjoin();  // 等線程thread結束後再繼續執行 
        Systemoutprintln(thread已經結束!);
        Systemoutprintln(isAlive:  + threadisAlive());
    }
}

  要注意一下在上面的代碼中使用了join方法這個方法的主要功能是保證線程的run方法完成後程序才繼續運行這個方法將在後面的文章中介紹

  上面代碼的運行結果

   isAlive: false
isAlive: true
thread已經結束!
isAlive: false

  掛起和喚醒線程

  一但線程開始執行run方法就會一直到這個run方法執行完成這個線程才退出但在線程執行的過程中可以通過兩個方法使線程暫時停止執行這兩個方法是suspend和sleep在使用suspend掛起線程後可以通過resume方法喚醒線程而使用sleep使線程休眠後只能在設定的時間後使線程處於就緒狀態(在線程休眠結束後線程不一定會馬上執行只是進入了就緒狀態等待著系統進行調度)

  雖然suspend和resume可以很方便地使線程掛起和喚醒但由於使用這兩個方法可能會造成一些不可預料的事情發生因此這兩個方法被標識為deprecated(抗議)標記這表明在以後的jdk版本中這兩個方法可能被刪除所以盡量不要使用這兩個方法來操作線程下面的代碼演示了sleepsuspend和resume三個方法的使用

   package chapter;

public class MyThread extends Thread
{
    class SleepThread extends Thread
    {
        public void run()
        {
            try
            {
                sleep();
            }
            catch (Exception e)
            {
            }
        }
    }
    public void run()
    {
        while (true)
            Systemoutprintln(new javautilDate()getTime());
    }
    public static void main(String[] args) throws Exception
    {
        MyThread thread = new MyThread();
        SleepThread sleepThread = threadnew SleepThread();
        sleepThreadstart(); // 開始運行線程sleepThread
        sleepThreadjoin();  // 使線程sleepThread延遲
        threadstart();
        boolean flag = false;
        while (true)
        {
            sleep();  // 使主線程延遲
            flag = !flag;
            if (flag)
                threadsuspend(); 
            else
                threadresume();
        }
    }
}

  從表面上看使用sleep和suspend所產生的效果類似但sleep方法並不等同於suspend它們之間最大的一個區別是可以在一個線程中通過suspend方法來掛起另外一個線程如上面代碼中在主線程中掛起了thread線程而sleep只對當前正在執行的線程起作用在上面代碼中分別使sleepThread和主線程休眠了秒和在使用sleep時要注意不能在一個線程中來休眠另一個線程如main方法中使用threadsleep()方法是無法使thread線程休眠秒的而只能使主線程休眠

  在使用sleep方法時有兩點需要注意

   sleep方法有兩個重載形式其中一個重載形式不僅可以設毫秒而且還可以設納秒(納秒等於毫秒)但大多數操作系統平台上的Java虛擬機都無法精確到納秒因此如果對sleep設置了納秒Java虛擬機將取最接近這個值的毫秒

   在使用sleep方法時必須使用throws或try{……}catch{……}因為run方法無法使用throws所以只能使用try{……}catch{……}當在線程休眠的過程中使用interrupt方法(這個方法將在中討論)中斷線程時sleep會拋出一個InterruptedException異常sleep方法的定義如下

   public static void sleep(long millis)  throws InterruptedException
public static void sleep(long millis  int nanos)  throws InterruptedException

  終止線程的三種方法

  有三種方法可以使終止線程

    使用退出標志使線程正常退出也就是當run方法完成後線程終止

    使用stop方法強行終止線程(這個方法不推薦使用因為stop和suspendresume一樣也可能發生不可預料的結果)

    使用interrupt方法中斷線程

   使用退出標志終止線程

  當run方法執行完後線程就會退出但有時run方法是永遠不會結束的如在服務端程序中使用線程進行監聽客戶端請求或是其他的需要循環處理的任務在這種情況下一般是將這些任務放在一個循環中如while循環如果想讓循環永遠運行下去可以使用while(true){……}來處理但要想使while循環在某一特定條件下退出最直接的方法就是設一個boolean類型的標志並通過設置這個標志為true或false來控制while循環是否退出下面給出了一個利用退出標志終止線程的例子

   package chapter;

public class ThreadFlag extends Thread
{
    public volatile boolean exit = false;

    public void run()
    {
        while (!exit);
    }
    public static void main(String[] args) throws Exception
    {
        ThreadFlag thread = new ThreadFlag();
        threadstart();
        sleep(); // 主線程延遲
        threadexit = true;  // 終止線程thread
        threadjoin();
        Systemoutprintln(線程退出!);
    }
}

  在上面代碼中定義了一個退出標志exit當exit為true時while循環退出exit的默認值為false在定義exit時使用了一個Java關鍵字volatile這個關鍵字的目的是使exit同步也就是說在同一時刻只能由一個線程來修改exit的值

   使用stop方法終止線程

  使用stop方法可以強行終止正在運行或掛起的線程我們可以使用如下的代碼來終止線程

   threadstop();

  雖然使用上面的代碼可以終止線程但使用stop方法是很危險的就象突然關閉計算機電源而不是按正常程序關機一樣可能會產生不可預料的結果因此並不推薦使用stop方法來終止線程

   使用interrupt方法終止線程

  使用interrupt方法來終端線程可分為兩種情況

  ()線程處於阻塞狀態如使用了sleep方法

  ()使用while(!isInterrupted()){……}來判斷線程是否被中斷

  在第一種情況下使用interrupt方法sleep方法將拋出一個InterruptedException例外而在第二種情況下線程將直接退出下面的代碼演示了在第一種情況下使用interrupt方法

   package chapter;

public class ThreadInterrupt extends Thread
{
    public void run()
    {
        try
        {
            sleep();  // 延遲
        }
        catch (InterruptedException e)
        {
            Systemoutprintln(egetMessage());
        }
    }
    public static void main(String[] args) throws Exception
    {
        Thread thread = new ThreadInterrupt();
        threadstart();
        Systemoutprintln(秒之內按任意鍵中斷線程!);
        Systeminread();
        threadinterrupt();
        threadjoin();
        Systemoutprintln(線程已經退出!);
    }
}

  上面代碼的運行結果如下

       在秒之內按任意鍵中斷線程!

    sleep interrupted
    線程已經退出!

  在調用interrupt方法後 sleep方法拋出異常然後輸出錯誤信息sleep interrupted

  注意在Thread類中有兩個方法可以判斷線程是否通過interrupt方法被終止一個是靜態的方法interrupted()一個是非靜態的方法isInterrupted()這兩個方法的區別是interrupted用來判斷當前線是否被中斷而isInterrupted可以用來判斷其他線程是否被中斷因此while (!isInterrupted())也可以換成while (!Threadinterrupted())


From:http://tw.wingwit.com/Article/program/Java/gj/201311/11154.html
    推薦文章
    Copyright © 2005-2022 電腦知識網 Computer Knowledge   All rights reserved.