多線程——線程的生命週期

Java中,線程從建立到結束,共分爲5個狀態。一個線程在其生命週期內,老是處於某種狀態:ide

  • 建立狀態
  • 可運行狀態
  • 不可運行狀態
  • 死亡狀態

1、建立狀態this

執行下列語句時,線程就處於建立狀態:
       Thread myThread = new MyThreadClass( );spa

當一個線程處於建立狀態時,它僅僅是一個空的線程對象,系統不爲它分配資源。.net

2、可運行狀態線程

Thread myThread = new MyThreadClass( );
       myThread.start( );
      當一個線程處於可運行狀態時,系統爲這個線程分配了它需的系統資源,安排其運行並調用線程運行方法,這樣就使得該線程處於可運行   ( Runnable )狀態。對象

注意:blog

這一狀態並非運行中狀態(Running ),由於線程也許實際上並未真正運行。單處理器的計算機要在同一時刻運行全部的處於可運行狀態的線程是不可能的,Java的運行系統必須實現調度來保證這些線程共享處理器。 生命週期

3、不可運行狀態ci

當下面5種狀況發生時,線程就進入不可運行狀態:資源

(1) 調用了sleep()方法;

(2) 調用了suspend()方法;

(3) 爲等候一個條件變量,線程調用wait()方法;

(4) 輸入輸出流中發生線程阻塞。

(5)線程試圖調用另外一個對象的「同步」方法,但那個對象處於對象鎖定狀態,暫時沒法使用

上面5種狀況,要使線程返回可運行狀態,各有特定的方法與之對應:

1) 若是線程處於睡眠狀態中,sleep()方法中的參數爲睡眠時間,當這個時間過去後,線程即爲可運行的;

2) 若是一個線程被掛起,要使該線程從新處於可運行狀態,需調用resume()方法;

3) 若是線程在等待條件變量,那麼要中止等待的話,須要該條件變量的線程對象調用notifyAll()方法;

4) 若是在I/O流中發生線程阻塞,則特定的I/O完成後可結束這種不可運行狀態。

5) 同步的方法完成,釋放了同步鎖

4、死亡狀態

線程的終止通常可經過兩種方法實現:

(1)天然撤消

(2)調用stop()方法中止當前線程

總結: 線程的生命週期、運行狀態和轉換:

image

5、決定線程生命週期的相關方法:

1)、join方法:

         t.join( )方法使當前的線程等待,直到 t 結束爲止,線程恢復到運行(runnable)狀態

三種調用格式:

①join():如當前線程發出調用t.join(),則當前線程將等待線程 t結束後在繼續執行。

②join(long millis):如當前線程發出調用t.join(),則當前線程將等待線程t結束或最多等待mills毫秒後在繼續執行。

③join(long millis,long nanos) throws InterruptedException

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
 
package com.model.elgin.thread;

public   class TestThread1 {
   
   
public   static   void main( String [] args)  {
         MyThread mt1=
new MyThread();
         MyThread1 mt2=
new MyThread1();
        
//setName方法爲線程命名
         mt1.setName( "mt1" );
         mt2.setName(
"mt2" );;
        
//start方法開啓線程
         mt1.start(); 
        
/*try {
            mt1.join();
         } catch (InterruptedException e) {
            e.printStackTrace();
         }*/

         mt2.start();
    }
        
}
    
class MyThread extends Thread{
    
    @Override
   
public   void run() {
       
for ( int i = 0 ; i < 10 ; i++) {
           
//currentThread()爲Thread類的靜態方法,做用是獲得當前正在運行的線程 
            System.out.println(Thread.currentThread().getName() + ": Hello thread1-" + i);
        }
    }
    
}

class MyThread1 extends Thread{
    
    @Override
   
public   void run() {
       
for ( int i = 0 ; i < 10 ; i++) {
           
//currentThread()爲Thread類的靜態方法,做用是獲得當前正在運行的線程 
            System.out.println(Thread.currentThread().getName() + ": Hello thread2-" + i);
        }
    }   
}

加入join方法和未加入join方法(上述代碼13-17行)運行結果比較:

能夠看出加入join方法以後,先執行完mt1線程再去執行mt2.而未加入的時候則無規律。

image   image

2)、interrupt()方法:中斷線程

若是一個線程t在調用sleep()、join()、wait()等方法被阻塞時,則t.interrupt()方法將中斷t的阻塞狀態,並將接收到InterruptException對象。

3)、isDaemon()和setDaemon()方法

  • 線程可分爲守護線程與用戶線程
  • 當一個程序中只有一個守護線程在運行,程序會當即退出;若是一個程序還有正在運行的用戶線程,該程序不會停止。
  • 判斷一個線程是用戶線程仍是守護線程,用isDaemon()方法
  • 將一個線程設置爲守護線程用setDaemon()方法

4)、結束線程

  • 線程完成運行並結束後,將不能再運行。
  • 除正常運行結束外,還可用其餘方法控制使其中止。
    •   用stop( )方法,已過期

                           強行終止線程,容易形成線程的不一致。

    • 使用標誌flag。

                         經過設置flag 指明run( )方法應該結束。

示例:

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
 
package com.model.elgin.thread;

public   class TestThread3 {
   
public   static   void main( String [] args) {
        StopThread st=
new StopThread();
        Thread t=
new Thread(st);
        System.out.println(
"say hello start..." );
        t.setPriority(Thread.MAX_PRIORITY);
        t.start();
        System.out.println(
"stop say hello..." );
        st.stopSayHello();
    }
}

class StopThread implements Runnable{
    
       
private   boolean flag=false;
       
int i= 0 ;
       
public   void run() {
           
while (!flag){
                System.out.println(
"Hello" +i++);
            }
        }
        
       
public   void stopSayHello(){
           
this .flag=true;         }    }
相關文章
相關標籤/搜索