1. 程式人生 > >java執行緒的常用方法

java執行緒的常用方法

java執行緒的常用方法

 

編號 方法 說明
1 public void start() 使該執行緒開始執行;Java 虛擬機器呼叫該執行緒的 run 方法。
2 public void run() 如果該執行緒是使用獨立的 Runnable 執行物件構造的,則呼叫該 Runnable 物件的 run 方法;否則,該方法不執行任何操作並返回。
3 public final void setName(String name) 改變執行緒名稱,使之與引數 name 相同。
4 public final void setPriority(int priority) 更改執行緒的優先順序。
5 public final void setDaemon(boolean on) 將該執行緒標記為守護執行緒或使用者執行緒。
6 public final void join(long millisec) 等待該執行緒終止的時間最長為 millis 毫秒。
7 public void interrupt() 中斷執行緒。
8 public final boolean isAlive() 測試執行緒是否處於活動狀態。
9 public static void yield() 暫停當前正在執行的執行緒物件,並執行其他執行緒。
10 public static void sleep(long millisec) 在指定的毫秒數內讓當前正在執行的執行緒休眠(暫停執行),此操作受到系統計時器和排程程式精度和準確性的影響。
11 public static Thread currentThread()
返回對當前正在執行的執行緒物件的引用。

 

一:靜態方法

(1)currentThread()方法

currentThread()方法可以返回程式碼段正在被哪個執行緒呼叫的資訊。

1 2 3 4 5 public class Run1{     public static void main(String[] args){                     System.out.println(Thread.currentThread().getName());     } }

(2)sleep()方法

方法sleep()的作用是在指定的毫秒數內讓當前“正在執行的執行緒”休眠(暫停執行)。這個“正在執行的執行緒”是指this.currentThread()返回的執行緒。

sleep方法有兩個過載版本:

1 2 sleep(long millis)     //引數為毫秒 sleep(long millis,int nanoseconds)    //第一引數為毫秒,第二個引數為納秒

sleep相當於讓執行緒睡眠,交出CPU,讓CPU去執行其他的任務。
但是有一點要非常注意,sleep方法不會釋放鎖,也就是說如果當前執行緒持有對某個物件的鎖,則即使呼叫sleep方法,其他執行緒也無法訪問這個物件。看下面這個例子就清楚了:

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 public class Test {       private int i = 10;     private Object object = new Object();       public static void main(String[] args) throws IOException  {         Test test = new Test();         MyThread thread1 = test.new MyThread();         MyThread thread2 = test.new MyThread();         thread1.start();         thread2.start();     }       class MyThread extends Thread{         @Override         public void run() {             synchronized (object) {                 i++;                 System.out.println("i:"+i);                 try {                     System.out.println("執行緒"+Thread.currentThread().getName()+"進入睡眠狀態");                     Thread.currentThread().sleep(10000);                 } catch (InterruptedException e) {                     // TODO: handle exception                 }                 System.out.println("執行緒"+Thread.currentThread().getName()+"睡眠結束");                 i++;                 System.out.println("i:"+i);             }         }     } }

輸出結果:

從上面輸出結果可以看出,當Thread-0進入睡眠狀態之後,Thread-1並沒有去執行具體的任務。只有當Thread-0執行完之後,此時Thread-0釋放了物件鎖,Thread-1才開始執行。

注意,如果呼叫了sleep方法,必須捕獲InterruptedException異常或者將該異常向上層丟擲。當執行緒睡眠時間滿後,不一定會立即得到執行,因為此時可能CPU正在執行其他的任務。所以說呼叫sleep方法相當於讓執行緒進入阻塞狀態。

(3)yield()方法

呼叫yield方法會讓當前執行緒交出CPU許可權,讓CPU去執行其他的執行緒。它跟sleep方法類似,同樣不會釋放鎖。但是yield不能控制具體的交出CPU的時間,另外,yield方法只能讓擁有相同優先順序的執行緒有獲取CPU執行時間的機會。

注意,呼叫yield方法並不會讓執行緒進入阻塞狀態,而是讓執行緒重回就緒狀態,它只需要等待重新獲取CPU執行時間,這一點是和sleep方法不一樣的。
程式碼:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public class MyThread  extends Thread{     @Override     public void run() {         long beginTime=System.currentTimeMillis();         int count=0;         for (int i=0;i<50000000;i++){             count=count+(i+1);             //Thread.yield();         }         long endTime=System.currentTimeMillis();         System.out.println("用時:"+(endTime-beginTime)+" 毫秒!");     } }   public class Run {     public static void main(String[] args) {         MyThread t= new MyThread();         t.start();     } }

執行結果:

1 用時: 3 毫秒!

如果將 //Thread.yield();的註釋去掉,執行結果如下:

1 用時: 16080 毫秒!

二:物件方法

(1)start()方法

start()用來啟動一個執行緒,當呼叫start方法後,系統才會開啟一個新的執行緒來執行使用者定義的子任務,在這個過程中,會為相應的執行緒分配需要的資源。

(2)run()方法

run()方法是不需要使用者來呼叫的,當通過start方法啟動一個執行緒之後,當執行緒獲得了CPU執行時間,便進入run方法體去執行具體的任務。注意,繼承Thread類必須重寫run方法,在run方法中定義具體要執行的任務。

(3)getId()

getId()的作用是取得執行緒的唯一標識
程式碼:

1 2 3 4 5 6 public class Test {     public static void main(String[] args) {         Thread t= Thread.currentThread();         System.out.println(t.getName()+" "+t.getId());     } }

輸出:

1 main 1

(4)isAlive()方法

方法isAlive()的功能是判斷當前執行緒是否處於活動狀態
程式碼:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 public class MyThread  extends Thread{     @Override     public void run() {         System.out.println("run="+this.isAlive());     } } public class RunTest {     public static void main(String[] args) throws InterruptedException {         MyThread myThread=new MyThread();         System.out.println("begin =="+myThread.isAlive());         myThread.start();         System.out.println("end =="+myThread.isAlive());     } }

程式執行結果:

1 2 3 begin ==false run=true end ==false

方法isAlive()的作用是測試執行緒是否偶處於活動狀態。什麼是活動狀態呢?活動狀態就是執行緒已經啟動且尚未終止。執行緒處於正在執行或準備開始執行的狀態,就認為執行緒是“存活”的。
有個需要注意的地方

1 System.out.println("end =="+myThread.isAlive());

雖然上面的例項中列印的值是true,但此值是不確定的。列印true值是因為myThread執行緒還未執行完畢,所以輸出true。如果程式碼改成下面這樣,加了個sleep休眠:

1 2 3 4 5 6 7 public static void main(String[] args) throws InterruptedException {         MyThread myThread=new MyThread();         System.out.println("begin =="+myThread.isAlive());         myThread.start();         Thread.sleep(1000);         System.out.println("end =="+myThread.isAlive());     }

則上述程式碼執行的結果輸出為false,因為mythread物件已經在1秒之內執行完畢。

(5)join()方法

在很多情況下,主執行緒建立並啟動了執行緒,如果子執行緒中藥進行大量耗時運算,主執行緒往往將早於子執行緒結束之前結束。這時,如果主執行緒想等待子執行緒執行完成之後再結束,比如子執行緒處理一個數據,主執行緒要取得這個資料中的值,就要用到join()方法了。方法join()的作用是等待執行緒物件銷燬。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 public class Thread4 extends Thread{     public Thread4(String name) {         super(name);     }     public void run() {         for (int i = 0; i < 5; i++) {             System.out.println(getName() + "  " + i);         }     }     public static void main(String[] args) throws InterruptedException {         // 啟動子程序         new Thread4("new thread").start();         for (int i = 0; i < 10; i++) {             if (i == 5) {                 Thread4 th = new Thread4("joined thread");                 th.start();                 th.join();             }             System.out.println(Thread.currentThread().getName() + "  " + i);         }     } }

執行結果:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 main  0 main  1 main  2 main  3 main  4 new thread  0 new thread  1 new thread  2 new thread  3 new thread  4 joined thread  0 joined thread  1 joined thread  2 joined thread  3 joined thread  4 main  5 main  6 main  7 main  8 main  9

由上可以看出main主執行緒等待joined thread執行緒先執行完了才結束的。如果把th.join()這行註釋掉,執行結果如下:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 main  0 main  1 main  2 main  3 main  4 main  5 main  6 main  7 main  8 main  9 new thread  0 new thread  1 new thread  2 new thread  3 new thread  4 joined thread  0 joined thread  1 joined thread  2 joined thread  3 joined thread  4

(6)getName和setName

用來得到或者設定執行緒名稱。

(7)getPriority和setPriority

用來獲取和設定執行緒優先順序。

(8)setDaemon和isDaemon

用來設定執行緒是否成為守護執行緒和判斷執行緒是否是守護執行緒。

守護執行緒和使用者執行緒的區別在於:守護執行緒依賴於建立它的執行緒,而使用者執行緒則不依賴。舉個簡單的例子:如果在main執行緒中建立了一個守護執行緒,當main方法執行完畢之後,守護執行緒也會隨著消亡。而使用者執行緒則不會,使用者執行緒會一直執行直到其執行完畢。在JVM中,像垃圾收集器執行緒就是守護執行緒。

在上面已經說到了Thread類中的大部分方法,那麼Thread類中的方法呼叫到底會引起執行緒狀態發生怎樣的變化呢?下面一幅圖就是在上面的圖上進行改進而來的: