<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆 - 312, 文章 - 14, 評論 - 1393, 引用 - 0
    數據加載中……

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

    本文為原創,如需轉載,請注明作者和出處,謝謝!

    上一篇:Java多線程初學者指南(3):使用Runnable接口創建線程

        與人有生老病死一樣,線程也同樣要經歷開始(等待)、運行、掛起和停止四種不同的狀態。這四種狀態都可以通過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 chapter2;

    public class LifeCycle extends Thread
    {
        
    public void run()
        {
            
    int n = 0;
            
    while ((++n) < 1000);        
        }
         
        
    public static void main(String[] args) throws Exception
        {
            LifeCycle thread1 
    = new LifeCycle();
            System.out.println(
    "isAlive: " + thread1.isAlive());
            thread1.start();
            System.out.println(
    "isAlive: " + thread1.isAlive());
            thread1.join();  
    // 等線程thread1結束后再繼續執行 
            System.out.println("thread1已經結束!");
            System.out.println(
    "isAlive: " + thread1.isAlive());
        }
    }

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

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

    二、掛起和喚醒線程

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

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

    package chapter2;

    public class MyThread extends Thread
    {
        
    class SleepThread extends Thread
        {
            
    public void run()
            {
                
    try
                {
                    sleep(
    2000);
                }
                
    catch (Exception e)
                {
                }
            }
        }
        
    public void run()
        {
            
    while (true)
                System.out.println(
    new java.util.Date().getTime());
        }
        
    public static void main(String[] args) throws Exception
        {
            MyThread thread 
    = new MyThread();
            SleepThread sleepThread 
    = thread.new SleepThread();
            sleepThread.start(); 
    // 開始運行線程sleepThread
            sleepThread.join();  // 使線程sleepThread延遲2秒
            thread.start();
            
    boolean flag = false;
            
    while (true)
            {
                sleep(
    5000);  // 使主線程延遲5秒
                flag = !flag;
                
    if (flag)
                    thread.suspend(); 
                
    else
                    thread.resume();
            }
        }
    }

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

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

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

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

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

    三、終止線程的三種方法

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

    1.  使用退出標志,使線程正常退出,也就是當run方法完成后線程終止。

    2.  使用stop方法強行終止線程(這個方法不推薦使用,因為stopsuspend、resume一樣,也可能發生不可預料的結果)。

        3.  使用interrupt方法中斷線程。 

    1. 使用退出標志終止線程

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

    package chapter2;

    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();
            thread.start();
            sleep(
    5000); // 主線程延遲5秒
            thread.exit = true;  // 終止線程thread
            thread.join();
            System.out.println(
    "線程退出!");
        }
    }

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

    2. 使用stop方法終止線程

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

    thread.stop();

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

    3. 使用interrupt方法終止線程

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

    (1)線程處于阻塞狀態,如使用了sleep方法。

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

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

    package chapter2;

    public class ThreadInterrupt extends Thread
    {
        
    public void run()
        {
            
    try
            {
                sleep(
    50000);  // 延遲50秒
            }
            
    catch (InterruptedException e)
            {
                System.out.println(e.getMessage());
            }
        }
        
    public static void main(String[] args) throws Exception
        {
            Thread thread 
    = new ThreadInterrupt();
            thread.start();
            System.out.println(
    "在50秒之內按任意鍵中斷線程!");
            System.in.read();
            thread.interrupt();
            thread.join();
            System.out.println(
    "線程已經退出!");
        }
    }

    上面代碼的運行結果如下:

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

        sleep interrupted
        線程已經退出!

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

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

    下一篇:
    Java多線程初學者指南(5):join方法的使用





    Android開發完全講義(第2版)(本書版權已輸出到臺灣)

    http://product.dangdang.com/product.aspx?product_id=22741502



    Android高薪之路:Android程序員面試寶典 http://book.360buy.com/10970314.html


    新浪微博:http://t.sina.com.cn/androidguy   昵稱:李寧_Lining

    posted on 2009-03-11 12:15 銀河使者 閱讀(8274) 評論(3)  編輯  收藏 所屬分類: java 、 原創 、多線程

    評論

    # re: Java多線程初學者指南(4):線程的生命周期  回復  更多評論   

    挺經典的,學習了!謝謝作者
    2009-03-13 12:38 | Werther

    # re: Java多線程初學者指南(4):線程的生命周期  回復  更多評論   

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


    能手動調用一個線程的run方法來啟動它么?
    2009-04-19 11:30 | charlee

    # re: Java多線程初學者指南(4):線程的生命周期  回復  更多評論   

    啟動線程必須使用start方法,run方法是由系統負責調用的。如果直接調用run方法,并不是啟動線程,而是直接調用了類的一個普通方法,也就相當于將run變成了一個普通的方法。
    2009-04-19 11:49 | 銀河使者
    主站蜘蛛池模板: 亚洲成A∨人片在线观看不卡| 亚洲日韩乱码久久久久久| 久爱免费观看在线网站 | 亚洲二区在线视频| 又爽又黄无遮挡高清免费视频| 中文字幕无线码中文字幕免费| 亚洲国产成人九九综合| 又大又硬又爽免费视频| 久久久久免费看成人影片| 亚洲成a人无码亚洲成av无码| 亚洲欧洲日产国码av系列天堂| 三年片在线观看免费大全| 成人毛片100免费观看| 亚洲一区二区三区精品视频| 国产精品亚洲αv天堂无码| 麻豆视频免费观看| 国产在线观看免费av站| 亚洲永久网址在线观看| 久久99国产亚洲精品观看| 四虎永久免费地址在线观看| 1a级毛片免费观看| 国产乱妇高清无乱码免费| 亚洲熟妇AV一区二区三区宅男| 亚洲国产精品一区二区成人片国内| 国产麻豆剧传媒精品国产免费| 国偷自产一区二区免费视频| 在线观看亚洲视频| 亚洲欧洲日韩极速播放| 亚洲人成电影在线天堂| 国产啪亚洲国产精品无码| 老司机永久免费网站在线观看| 免费观看在线禁片| 一级毛片免费视频网站| 亚洲国产精品无码第一区二区三区| 亚洲日本va午夜中文字幕一区| 激情97综合亚洲色婷婷五| 国产一区二区三区免费视频| 国产免费毛不卡片| 91精品啪在线观看国产线免费| 男女拍拍拍免费视频网站| 美女被免费视频网站a|