Java知多少(65)線程的掛起、恢復和終止


有時,線程的掛起是很有用的。例如,一個獨立的線程可以用來顯示當日的時間。如果用戶不希望用時鍾,線程被掛起。在任何情形下,掛起線程是很簡單的,一旦掛起,重新啟動線程也是一件簡單的事。

掛起,終止和恢復線程機制在Java 2和早期版本中有所不同。盡管你運用Java 2的途徑編寫代碼,你仍需了解這些操作在早期Java環境下是如何完成的。例如,你也許需要更新或維護老的代碼。你也需要了解為什么Java 2會有這樣的變化。因為這些原因,下面內容描述了執行線程控制的原始方法,接着是Java 2的方法。

Java 1.1或更早版本的線程的掛起、恢復和終止

先於Java2的版本,程序用Thread 定義的suspend() 和 resume() 來暫停和再啟動線程。它們的形式如下:
    final void suspend( )
    final void resume( )
下面的程序描述了這些方法:

 1 // Using suspend() and resume().
 2 class NewThread implements Runnable {
 3     String name; // name of thread
 4     Thread t;
 5     NewThread(String threadname) {
 6         name = threadname;
 7         t = new Thread(this, name);
 8         System.out.println("New thread: " + t);
 9         t.start(); // Start the thread
10     }
11     // This is the entry point for thread.
12     public void run() {
13         try {
14             for(int i = 15; i > 0; i--) {
15                 System.out.println(name + ": " + i);
16                 Thread.sleep(200);
17             }
18         } catch (InterruptedException e) {
19             System.out.println(name + " interrupted.");
20         }
21         System.out.println(name + " exiting.");
22     }
23 }
24 class SuspendResume {
25     public static void main(String args[]) {
26         NewThread ob1 = new NewThread("One");
27         NewThread ob2 = new NewThread("Two");
28         try {
29             Thread.sleep(1000);
30             ob1.t.suspend();
31             System.out.println("Suspending thread One");
32             Thread.sleep(1000);
33             ob1.t.resume();
34             System.out.println("Resuming thread One");
35             ob2.t.suspend();
36             System.out.println("Suspending thread Two");
37             Thread.sleep(1000);
38             ob2.t.resume();
39             System.out.println("Resuming thread Two");
40         } catch (InterruptedException e) {
41             System.out.println("Main thread Interrupted");
42         }
43         // wait for threads to finish
44         try {
45             System.out.println("Waiting for threads to finish.");
46             ob1.t.join();
47             ob2.t.join();
48         } catch (InterruptedException e) {
49             System.out.println("Main thread Interrupted");
50         }
51         System.out.println("Main thread exiting.");
52     }
53 }

程序的部分輸出如下:

 1 New thread: Thread[One,5,main]
 2 One: 15
 3 New thread: Thread[Two,5,main]
 4 Two: 15
 5 One: 14
 6 Two: 14
 7 One: 13
 8 Two: 13
 9 One: 12
10 Two: 12
11 One: 11
12 Two: 11
13 Suspending thread One
14 Two: 10
15 Two: 9
16 Two: 8
17 Two: 7
18 Two: 6
19 Resuming thread One
20 Suspending thread Two
21 One: 10
22 One: 9
23 One: 8
24 One: 7
25 One: 6
26 Resuming thread Two
27 Waiting for threads to finish.
28 Two: 5
29 One: 5
30 Two: 4
31 One: 4
32 Two: 3
33 One: 3
34 Two: 2
35 One: 2
36 Two: 1
37 One: 1
38 Two exiting.
39 One exiting.
40 Main thread exiting.

Thread類同樣定義了stop() 來終止線程。它的形式如下:

    void stop( )
一旦線程被終止,它不能被resume() 恢復繼續運行。

Java 2中掛起、恢復和終止線程

Thread定義的suspend(),resume()和stop()方法看起來是管理線程的完美的和方便的方法,它們不能用於新Java版本的程序。下面是其中的原因。Thread類的suspend()方法在Java2中不被贊成,因為suspend()有時會造成嚴重的系統故障。假定對關鍵的數據結構的一個線程被鎖定的情況,如果該線程在那里掛起,這些鎖定的線程並沒有放棄對資源的控制。其他的等待這些資源的線程可能死鎖。

Resume()方法同樣不被贊同。它不引起問題,但不能離開suspend()方法而獨立使用。Thread類的stop()方法同樣在Java 2中受到反對。這是因為該方法可能導致嚴重的系統故障。設想一個線程正在寫一個精密的重要的數據結構且僅完成一個零頭。如果該線程在此刻終止,則數據結構可能會停留在崩潰狀態。

因為在Java 2中不能使用suspend(),resume()和stop() 方法來控制線程,你也許會想那就沒有辦法來停止,恢復和結束線程。其實不然。相反,線程必須被設計以使run() 方法定期檢查以來判定線程是否應該被掛起,恢復或終止它自己的執行。有代表性的,這由建立一個指示線程狀態的標志變量來完成。只要該標志設為“running”,run()方法必須繼續讓線程執行。如果標志為“suspend”,線程必須暫停。若設為“stop”,線程必須終止。

當然,編寫這樣的代碼有很多方法,但中心主題對所有的程序應該是相同的。

下面的例題闡述了從Object繼承的wait()和notify()方法怎樣控制線程的執行。該例與前面講過的程序很像。然而,不被贊同的方法都沒有用到。讓我們思考程序的執行。

NewTread 類包含了用來控制線程執行的布爾型的實例變量suspendFlag。它被構造函數初始化為false。Run()方法包含一個監測suspendFlag 的同步聲明的塊。如果變量是true,wait()方法被調用以掛起線程。Mysuspend()方法設置suspendFlag為true。Myresume()方法設置suspendFlag為false並且調用notify()方法來喚起線程。最后,main()方法被修改以調用mysuspend()和myresume()方法。

 1 // Suspending and resuming a thread for Java2
 2 class NewThread implements Runnable {
 3     String name; // name of thread
 4     Thread t;
 5     boolean suspendFlag;
 6     NewThread(String threadname) {
 7         name = threadname;
 8         t = new Thread(this, name);
 9         System.out.println("New thread: " + t);
10         suspendFlag = false;
11         t.start(); // Start the thread
12     }
13     // This is the entry point for thread.
14     public void run() {
15         try {
16             for(int i = 15; i > 0; i--) {
17                 System.out.println(name + ": " + i);
18                 Thread.sleep(200);
19                 synchronized(this) {
20                     while(suspendFlag) {
21                         wait();
22                     }
23                 }
24             }
25         } catch (InterruptedException e) {
26             System.out.println(name + " interrupted.");
27         }
28         System.out.println(name + " exiting.");
29     }
30     void mysuspend() {
31         suspendFlag = true;
32     }
33     synchronized void myresume() {
34         suspendFlag = false;
35         notify();
36     }
37 }
38 class SuspendResume {
39     public static void main(String args[]) {
40        NewThread ob1 = new NewThread("One");
41        NewThread ob2 = new NewThread("Two");
42        try {
43           Thread.sleep(1000);
44           ob1.mysuspend();
45           System.out.println("Suspending thread One");
46           Thread.sleep(1000);
47           ob1.myresume();
48           System.out.println("Resuming thread One");
49           ob2.mysuspend();
50           System.out.println("Suspending thread Two");
51           Thread.sleep(1000);
52           ob2.myresume();
53           System.out.println("Resuming thread Two");
54        } catch (InterruptedException e) {
55           System.out.println("Main thread Interrupted");
56        }
57        // wait for threads to finish
58        try {
59           System.out.println("Waiting for threads to finish.");
60           ob1.t.join();
61           ob2.t.join();
62        } catch (InterruptedException e) {
63            System.out.println("Main thread Interrupted");
64        }
65        System.out.println("Main thread exiting.");
66     }
67 }

該程序的輸出與前面的程序相同。此書的后面部分,你將看到用Java 2機制控制線程的更多例子。盡管這種機制不像老方法那樣“干凈”,然而,它是確保運行時不發生錯誤的方法。它是所有新的代碼必須采用的方法。

系列文章:


免責聲明!

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



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