線程,java線程

來源:互聯網
上載者:User

線程,java線程

本文原創,轉載請標明原處!

 

啟動與入口

Thread對象可操縱一個線程,而Runnable對象代表一個可被啟動並執行對象,必須使用Thread對象的start()方法啟動線程。啟動後,會先運行Thread對象的run()方法,這個方法未被重寫時,就會執行Runnable對象的run()方法。

主線程的入口是main()靜態方法,子線程的入口是Thread的run()方法。表示Thread與Runnable的區別:

 

運行與暫停

線程可以在運行中暫停,也可以從暫停中恢複運行,其暫停目有如下列舉:

  • 周期性處理:如每秒更新時間的顯示,就需要每次更新完時間後,線程休眠1秒。
  • 定時處理:讓線程休眠至指定時間運行。
  • 事件處理:讓線程休眠至事件觸發的時候運行。
  • 通行限制:在特定代碼塊裡,只允許一定數量或具備一定條件的線程進入,被限制的線程暫停於關卡處。
  • 確保即時資料:多線程共用資料時,讀取資料的時間點到使用資料的時間點,會有一個時間差,因此使用資料時,該資料並不是即時資料。為了確保即時資料,就需要在使用時,只有一個線程在使用,其它需要用到該資料的線程就會暫停。

表示,線程基本的暫停方式與恢複運行方式:

 

說明:圖中,虛線表示每次觸發時,只允許一條線程變化。Happen表示發生於其它線程,即非同步觸發。

有一點不太明確,也不知道怎麼去測試,就是Auto Yield,這裡我猜想加上去的。猜想的依據是根據一篇文章《Java中的多線程你只要看這一篇就夠了》。文中寫道,並行與並發的概念與區別,思考了一下,並行是多個人同時處理各自的事,換句話說同一時刻可以處理多件事。而並發是一個人同時處理多件事,但實際上是做不到的,因為同一時刻只能處理一件事。不知道這裡,我有沒有思考有誤,如果是這樣,那麼同一時刻,就只處理著一條線程。

 

結束與監聽

線程結束分為自然結束與強制中止。

自然結束,是指線程啟動時的入口方法結束,自然結束分為正常結束和異常結束。異常結束是以某個異常拋出作為起點一直往上拋出,而正常結束,需要監聽到結束的標誌後,處理關閉事項,需要處理上一段時間才能真正結束。

強制中止,在運行途中的任意位置結束,什麼時候中止,線程就什麼時候結束。可以使用stop()方法強制中止,也可以把把線程設定為目標線程的守護線程,這樣線程就會以目標線程結束而強制結束。強制中止,用於不需要維護重要資料的線程,即對重要資料不產生影響。

 

程式碼範例1:主線程以子線程對象作為同步鎖,然後使用wait(...)方法,當子線程結束時,就會喚醒wait(...)方法,從而達到主線程監聽子線程的結束。

public static void main(String[] args) throws InterruptedException {    Thread thread = new Thread(){        public void run(){            try {                Thread.sleep(1000);            } catch (InterruptedException e) {                e.printStackTrace();            }            System.out.println("子線程結束!");        }    };    thread.start();        // 相當於thread.join(),thread線程結束時,會調用thread.notifyAll()    synchronized(thread){        thread.wait();    }    System.out.println("主線程結束!");        // 輸出結果:    // 子線程結束!    // 主線程結束!}

實際上,join(...)方法裡面,用的就是這種方式監聽子線程的結束。因此,主線程使用join(...)方法後,子線程要切忌不能使用自己的線程對象作為同步鎖,那樣會造成死結。

 

程式碼範例2:主線程調用子線程的interrupt()方法,使子線程在wait()方法裡拋出異常,同時還驗證了interrupt()使子線程從wait()方法中喚醒後,依然需要同步阻塞。 

public static void main(String[] args) throws InterruptedException {    final Object lock = new Object();    Thread[] threads = new Thread[5];    for(int i=0; i<threads.length; i++){        final int num = i + 1;        Thread thread = new Thread(){            public void run(){                synchronized(lock){                    try {                        System.out.println("線程" + num + " -> 進入等待!");                        lock.wait();                    } catch (InterruptedException e) {                        // e.printStackTrace();                        System.out.println("線程" + num + " -> " + e);                    }                    System.out.println("線程" + num + " -> 退出等待!");                                        try {                        System.out.println("線程" + num + " -> 進入睡眠!");                        Thread.sleep(500);                    } catch (InterruptedException e) {                        // e.printStackTrace();                        System.out.println("線程" + num + " -> " + e);                    }                    System.out.println("線程" + num + " -> 睡眠結束,退出同步塊!");                                        Thread.currentThread().stop();                    System.out.println("線程" + num + " -> 結束沒有?");                }            }        };        thread.start();        threads[i] = thread;    }    System.out.println("主線程 -> 等待2秒!");    Thread.sleep(2000);    System.out.println("主線程 -> 中止所有線程!");        for(int i=0; i<threads.length; i++){        threads[i].interrupt();    }    for(int i=0; i<threads.length; i++){        threads[i].join();    }    System.out.println("主線程 -> 中止所有線程結束!");        /*         輸出結果:        線程1 -> 進入等待!        線程4 -> 進入等待!        主線程 -> 等待2秒!        線程3 -> 進入等待!        線程2 -> 進入等待!        線程5 -> 進入等待!        主線程 -> 中止所有線程!        線程1 -> 退出等待!        線程1 -> 進入睡眠!        線程1 -> 睡眠結束,退出同步塊!        線程4 -> 退出等待!        線程4 -> 進入睡眠!        線程4 -> 睡眠結束,退出同步塊!        線程3 -> 退出等待!        線程3 -> 進入睡眠!        線程3 -> 睡眠結束,退出同步塊!        線程2 -> 退出等待!        線程2 -> 進入睡眠!        線程2 -> 睡眠結束,退出同步塊!        線程5 -> 退出等待!        線程5 -> 進入睡眠!        線程5 -> 睡眠結束,退出同步塊!        主線程 -> 中止所有線程結束!     */}

  

程式碼範例3:子線程作為主線程的守護線程,因主線程的結束而強制中止。

public static void main(String[] args) throws InterruptedException {    Thread thread = new Thread(){        public void run(){            boolean run = true;            while(run){                System.out.println("子線程 -> 運行中……");                try {                    Thread.sleep(500);                } catch (InterruptedException e) {                    e.printStackTrace();                }            }            System.out.println("子線程 -> 正常退出!");        }    };    thread.setDaemon(true);    thread.start();        System.out.println("主線程 -> 2秒後結束");    Thread.sleep(2000);    System.out.println("主線程 -> 結束");        /*        運行結果:        主線程 -> 2秒後結束        子線程 -> 運行中……        子線程 -> 運行中……        子線程 -> 運行中……        子線程 -> 運行中……        子線程 -> 運行中……        主線程 -> 結束     */}

 

 待續更新……

 

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.