JWorld@TW the best professional Java site in Taiwan
      註冊 | 登入 | 全文檢索 | 排行榜  

» JWorld@TW » Java 新手區  

按列印兼容模式列印這個話題 列印話題    把這個話題寄給朋友 寄給朋友    訂閱主題
reply to topicthreaded modego to previous topicgo to next topic
本主題所含的標籤
無標籤
作者 [分享]Thread 淺介 [精華]
jocosn





發文: 102
積分: 5
於 2005-04-19 07:14 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
以下文章為個人當初學習 Java 時參照書本與網路的心得筆記。非本人原創。若有增添,請見本人個人網站。若有錯誤請留言討論。
紅色斜體字表示實做時需自行更改名稱替換
-----------------------------------------------------------------------------------------
■ Thread 執行緒
一、建立執行緒
執行緒的建立方法有多種
1. 實作 Runnable 介面
 [方法一]
  (步驟1) 實作 Runnable 介面,覆寫 run( ) 方法
1
2
3
4
     class ClassNameR implements Runnable {
       public void run( ) { .... }
       ....
     }
  (步驟2) 建立 Thread 物件,傳遞實作 Runnable 介面的 class 實體作為目標物
1
2
3
4
     ClassNameR  objX  = new ClassNameR( );
     Thread objT = new Thread(objX);  // 1
     objT.start( );  // 2
     // 或將1, 2 合寫成 new Thread(objX).start( );


 [方法二]
 以物件本身處理自己的執行緒,將 start( ) 寫在實作 Runnable 介面的 class 內的建構式或方法內
1
2
3
4
5
6
7
8
 class CalssNameR implements Runnable {
   Thread objThread;
   ClassNameR(String name) {
     objThread = new Thread(this);
     objThread.start( );
   }
   ..... 
 }

2. 繼承 Thread 類別
將類別變成可執行型態 Thread 的子類別,並應覆寫 run( ) 方法
 [方法一]
  (步驟1) 繼承 Thread 類別,覆寫 run( ) 方法
1
2
3
4
     class ClassNameT extends Thread {
       public void run( ) { . . . . }
       ....
     }
  (步驟2) 建立該 Thread 子類別的物件,呼叫由Thread 類別繼承而來的start( )方法
1
2
     ClassNameT objThread = new ClassNameT( );
     objThread.start( );


 [方法二]
 當物件建立便啟動執行緒,將start( ) 寫在繼承 Thread 類別的 class 內的建構式或方法內
1
2
3
4
5
6
  class CalssNameT extends Thread {
     ClassNameT(String name) {
      start( );
    }
    . . . .
  }



3. 混用繼承 Thread 類別與實作 Runnable 介面建立 adapter class
1
2
3
4
5
6
7
8
class ClassNameX {
  . . . . . .
  Thread objThread = new Thread( new Runnable( ) { 
    public void run( ){ ..... } } 
  );
  objThread.start( );
   . . . . . .
}


二、執行緒的啟動
執行緒類別建立好後,呼叫該類別所繼承的 start( ) 方法(一般而言我們不會去override 該 start( ) 方法),JVM會去自動執行run( )方法,便會啟動該執行緒

[範例]
1
2
3
4
5
6
7
8
9
10
11
public class MyThread {
  MyThread( ){   // 在建構子中作動作
    Runnable R = new Runnable( ){
      public void run( ){
        ...
      }
    };
    new Thread(R).start( );
  }
  ......
}



執行緒會有下列各種狀態發生 -- ready、waiting for some action、running、和 dead
(1) Prepared State 起始狀態
  使用new關鍵字建立一個Thread物件後,但未呼叫其start( )方法。
(2) Ready State 可執行狀態。
  此狀態下的執行緒已準備執行(execution)。
(3) Running State 執行中狀態 。
(4) Dead State 死亡狀態。
  當run( )方法執行完畢、不明的執行例外、不宜使用的 stop( ) 被呼叫會進入死亡狀態,進入死亡狀態的執行緒不能被重新啟動 。
(5) Waiting State 等待狀態
  等待某個 action 發生。當該action 發生,執行緒進入ready state。
  waiting thread 產生的情況 -如 sleeping、suspended、blocked、waiting for monitor。

◆ Java 啟動時基本上會執行的 threads
1. 2個 threads 為 main thread 和 garbage collection thread
2. 如果Java program 包含 graphical user interface(GUI),JavaVM 會自動再增加 threads
 a) 其中一個 thread 負責傳送 GUI events 到相對應的 methods
 b) 另一個 thread 負責繪製 GUI window

◆ Thread object 會耗用的資源
1. memory resources 和 processor resources
 a) threads 間的交換運作重新恢復執行狀態,此種情況稱做 context switch
   context switch 會耗用 CPU 資源
 b) starting、stopping、destroying 某個 Thread object 也會耗用資源
2. 每個 thread 會執行兩個動作,呼叫 JavaVM 對 stacks 的配置
 a) 其中一個 stack 用來紀錄和掌握 Java method calls 和 local variables 的狀態
 b) 另一個 stack 用作紀錄 native code (例如 C 語言) calls

◆ 當呼叫某個 thread 的 run() 方法時,該 thread 會被認為處於存活(alive)狀態,在 run() 結束並返回那刻,該 thread 死亡(die)。thread 死亡後,無法重新 restarted。
在 parent thread 內呼叫 start() 啟動另一個 thread 後會立刻 return 回到該 parent thread,而不會等待另一個 thread 啟動。在 start() 內,parent thread 傳送asynchronously signals 給 JVM 告知另一個 thread 應立刻盡快啟動。
新建立的 thread 在叫用 start() 方法後,可能在任何時刻進入 run() 方法內開始執行。
這意味 original thread 可能在start() 之後的 statement 執行前就被 swapped out。

[範例] 如果 original thread 執行下列程式碼
1
2
3
stmt1();    
anotherThread.start();    // A1  
stmt2();    


而新 thread 的 run() method 內的程式碼(亦即A1呼叫的程式碼)如下: 1
1
2
3
4
public void run() {    
   stmtA();  
   stmtB();  
 } 


則 statement 執行順序可能為 stmt1()、anotherThread.start()、stmt2()、stmtA()、stmtB()
或 stmt1()、anotherThread.start()、stmtA()、stmtB()、stmt2() 等

◆ Thread 的 Life Cycle


◆ 練習
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class ThreadTest1 { 
   public static void main(String[] args){ 
 
       MyThread T = new MyThread(); 
       MyRunnable R = new MyRunnable(); 
       Thread TR = new Thread(R); 
 
       T.start();     // 會印出什麼 ? 
       TR.start();  // 會印出什麼 ? 
   } 
} 
 
class MyThread extends Thread { 
   public void start(){ 
        System.out.println("MyThread start...");   // L1 
   } 
   public void run(){ 
        System.out.println("MyThread run...");     // L2 
   } 
} 
 
class MyRunnable implements Runnable { 
   public void start(){ 
        System.out.println("MyRunnable start...");    // L3 
   } 
   public void run(){ 
        System.out.println("MyRunnable run...");     // L4 
   } 
} 

結果是
1
2
MyThread start... 
MyRunnable run... 


■ synchronized 的用法
1. 使用synchronized修飾方法
 object-level lock
 A)
1
2
3
4
5
6
7
synchronized returnType myMethod( ) { …… }
  相當於
  returnType  myMethod( ) {
    synchronized(this) {
      . . . . . .  
    }  
  }

 b) synchronized也可以當敘述使用
1
2
3
  synchronized (物件) {
    //物件同步區
  } 

  synchronized 的同步化對象其實是物件實體,因此 synchronized 不能用來修飾屬性、建構子或類別。

 Class locks
 static methods 使用 synchronized
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class Test {
  int count;
  synchronized void add( ) { count++; }
  static int classCount;
  static synchronized void classAdd( ) {
    classCount++;
  }
}
 
可寫成
class Test {
  int count;
  void add( ) {
    synchronized (this) {
      count++;
    }
  }
  static int classCount;
  static void classAdd( ) {
    try {
      synchronized (Class.forName("Test")) {
        classCount++;
      }
    } catch (ClassNotFoundException e) {
      ......
    }
  }
}


3. 使用 synchronized 關鍵字修飾操作共同資源的方法,可以讓該方法不會被兩個以上的執行緒同時使用,也就是在某個時間頂多只會有一個執行緒在使用該方法。

4. 擁有synchronized修飾的方法之物件,就是一個監視器(monitor),監視器會讓物件內的synchronized方法只讓一個執行緒使用。

5. 若物件中的所有方法都使用 sysnchronized 修飾,則在某個時間點只會有一個方法被執行。因為,Monitor 是物件而不是方法

6. wait( )、notify( ) 和 notifyAll( ) 方法只能使用於 synchronized 修飾的方法或 synchronized 敘述中
 A> wait( )方法是讓執行緒進入等待的狀態(waiting pool),同時「放棄物件的使用權」
 B> wait( ) 和 sleep( ) 兩者都可以讓執行緒進入等待狀態,不過 sleep( ) 並不會放棄物件的使用權
 C> notify( ) 會隨機叫醒 waiting pool 中的某個執行緒,而 nitifyAll( ) 則是叫醒 waiting pool 中所有的執行緒。

[注意事項]
• Overridden synchronized methods remain synchronized from a superclass. No need to synchronize the subclass methods.
• Never synchronize a constructor
• Synchronizing Methods of Inner Classes
 A> Inner classes can complicate synchronization of methods
 B> An inner class and its enclosing class are independent with regard to synchronization
 C> If a method of an inner class needs to access fields of the enclosing class, use synchronized to obtain a lock on the enclosing instance before accessing or modifying fields of the enclosing instance of the class.


jocosn edited on 2005-04-21 02:07
reply to postreply to post
作者 Re:[分享]Thread 淺介 [Re:jocosn]
gift2u

选择是人生最痛苦和快乐的过程



發文: 235
積分: 2
於 2005-04-21 14:54 user profilesend a private message to usersend email to gift2ureply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
jocosn wrote:

◆ 練習
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class ThreadTest1 { 
   public static void main(String[] args){ 
 
       MyThread T = new MyThread(); 
       MyRunnable R = new MyRunnable(); 
       Thread TR = new Thread(R); 
 
       T.start();     // 會印出什麼 ? 
       TR.start();  // 會印出什麼 ? 
   } 
} 
 
class MyThread  extends Thread { 
   public void start(){ 
        System.out.println("MyThread start...");   // L1 
   } 
   public void run(){ 
        System.out.println("MyThread run...");     // L2 
   } 
} 
 
class MyRunnable implements Runnable { 
   public void start(){ 
        System.out.println("MyRunnable start...");    // L3 
   } 
   public void run(){ 
        System.out.println("MyRunnable run...");     // L4 
   } 
} 

結果是
1
2
MyThread start... 
MyRunnable run... 


这个结果的出现应该是因为在MyThread 当中覆写了start方法。由此并不会自动地调用其中的run方法了。那如果他的start方法的第一句中加入super.start();则会出现这样的结果:
1
2
3
MyThread start...
MyThread run...
MyRunnable run...
Big Smile
那为什么不是
1
2
3
MyThread run...
MyThread start...
MyRunnable run...

呢?
[?]


gift2u edited on 2005-04-21 15:00
reply to postreply to post
哪怕前方的荆棘,
刺得我鲜血淋漓。
哪怕苦苦的追求,
仍创不出奇迹。
就让我,
再试飞一次吧,
天空会记下我执着的羽翼。
作者 Re:[分享]Thread 淺介 [Re:gift2u]
Duncan

還隱隱作痛

版主

發文: 7816
積分: 39
於 2005-04-21 16:01 user profilesend a private message to usersend email to Duncanreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
gift2u wrote:
这个结果的出现应该是因为在MyThread 当中覆写了start方法。由此并不会自动地调用其中的run方法了。那如果他的start方法的第一句中加入super.start();则会出现这样的结果:
1
2
3
MyThread start...
MyThread run...
MyRunnable run...
Big Smile
那为什么不是
1
2
3
MyThread run...
MyThread start...
MyRunnable run...

呢?
[?]


二者皆有可能。super.start() 執行後兵分二路,哪一路先殺到是不確定的。


reply to postreply to post

給我
辣味豆腐 其餘免談
作者 Re:[分享]Thread 淺介 [Re:Duncan]
gift2u

选择是人生最痛苦和快乐的过程



發文: 235
積分: 2
於 2005-04-21 16:42 user profilesend a private message to usersend email to gift2ureply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
Duncan wrote:
二者皆有可能。super.start() 執行後兵分二路,哪一路先殺到是不確定的。

按照Java构造函数里面的super所起的作用,在构造一个类的时候应该是调用base class的构造方法。然后才调用derrived class的构造方法。按照这个delegate的逻辑,应当是让base class 先作事情才对。Question所以我才会猜测在调用已经实例化的一个方法的时候会不会有类似的调用顺序。
但是~~~
我在JBUilder里反复的调用了这个方法结果真的只是:

1
2
3
MyThread start...
MyThread run...
MyRunnable run...

而一次也没有出现
1
2
3
MyThread run...
MyThread start...
MyRunnable run...


除非:
1
2
3
4
5
6
7
8
9
10
class MyThread extends Thread { 
   public void start(){ 
     super.start();
       this.yield();
        System.out.println("MyThread start...");   // L1 
   } 
   public void run(){ 
        System.out.println("MyThread run...");     // L2 
   } 
} 
StupidStupidStupid


reply to postreply to post
哪怕前方的荆棘,
刺得我鲜血淋漓。
哪怕苦苦的追求,
仍创不出奇迹。
就让我,
再试飞一次吧,
天空会记下我执着的羽翼。
作者 Re:[分享]Thread 淺介 [Re:gift2u]
Duncan

還隱隱作痛

版主

發文: 7816
積分: 39
於 2005-04-21 17:59 user profilesend a private message to usersend email to Duncanreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
gift2u wrote:
按照Java构造函数里面的super所起的作用,在构造一个类的时候应该是调用base class的构造方法。然后才调用derrived class的构造方法。按照这个delegate的逻辑,应当是让base class 先作事情才对。:?)所以我才会猜测在调用已经实例化的一个方法的时候会不会有类似的调用顺序。
但是~~~
我在JBUilder里反复的调用了这个方法结果真的只是:

1
2
3
MyThread start...
MyThread run...
MyRunnable run...

而一次也没有出现
1
2
3
MyThread run...
MyThread start...
MyRunnable run...



這個例子其實和下面這個例子(A 與 B 哪一個先出現?)是等效:
1
2
3
4
5
6
7
8
9
public static void main(String[] args) {
  new Thread() {
    public void run()
    {
      System.out.println("A");
    }
  }.start(); 
  System.out.println("B");
}


儘管你在某特定 VM 上測試的結果總是看到 B 先印出,不表示在其他平台與其他 VM 上的行為都是如此。

Thread - start API doc 講明 start method(也就是你例子中的 super.start();) 執行後,會有兩個 thread 同時進行,一個 thread 跑 run method,一個 thread 跑 start method return 後接下來的碼。兩個 thread 沒有任何同步的機制作用,兩著是獨立進行,順序上不確定。


reply to postreply to post

給我
辣味豆腐 其餘免談
作者 Re:[分享]Thread 淺介 [Re:jocosn]
chenmingyen

 



發文: 98
積分: 4
於 2005-12-09 14:09 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
可以麻煩一下, 修改code的顏色那些tag嗎??Black Eye

程式看起來很困難.Dead


chenmingyen edited on 2007-01-09 14:00
reply to postreply to post
作者 Re:[分享]Thread 淺介 [Re:chenmingyen]
browser

戀香

版主

發文: 3570
積分: 1
於 2005-12-09 14:10 user profilesend a private message to usersend email to browserreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
chenmingyen wrote:
可以修改一下code的顏色那些tag嗎??

程式看起來很困難


下禮拜修改此 bug ...
再忍耐一下吧 ...

Orz


reply to postreply to post
» JWorld@TW »  Java 新手區

reply to topicthreaded modego to previous topicgo to next topic
  已讀文章
  新的文章
  被刪除的文章
Jump to the top of page

JWorld@TW 本站商標資訊

Powered by Powerful JuteForum® Version Jute 1.5.8