[多線程] 線程中的常用方法-最詳細


線程中常用的方法

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 piority) 更改線程的優先級。

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 static yield() 暫停當前正在執行的線程對象,並執行其他線程。

10、public static void sleep(long millisec) 在指定的毫秒數內讓當前正在執行的線程休眠(暫停執行),此操作受到系統計時器和調度程序精度和准確性的影響。

11、public static Thread currentThread() 返回對當前正在執行的線程對象的引用。

配一張圖:

 

靜態方法:

1、currentThread()方法

    public static void main(String[] args) {

        System.out.println(Thread.currentThread().getName());
    }

結果:

main

因為是在main函數中運行的,所以得到的名字是main

 

2、sleep()方法

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

sleep方法有兩個重載版本

        Thread.sleep(int millis);//參數為休眠的毫秒
        Thread.sleep(int millis, int nanos);//第一個為休眠的毫秒,第二個為納秒

sleep相當於讓線程睡眠,交出CPU,讓CPU去執行其他的任務。
但是有一點要非常注意,sleep方法不會釋放鎖,也就是說如果當前線程持有對某個對象的鎖,則即使調用sleep方法,其他線程也無法訪問這個對象。如:

 1 /**
 2  * 線程的sleep方法
 3  *
 4  */
 5 public class SleepMethod {
 6     private int i = 10;
 7     private Object object = new Object();
 8 
 9     public static void main(String[] args) {
10         SleepMethod sm = new SleepMethod();
11         MyThread t1 = sm.new MyThread();
12         MyThread t2 = sm.new MyThread();
13         t1.start();
14         t2.start();
15     }
16 
17     class MyThread extends Thread {
18         @Override
19         public void run() {
20             synchronized (object) {
21                 i++;
22 
23                 try {
24                     System.out.println("I:" + i);
25                     System.out.println("Thread Name:" + Thread.currentThread().getName() + ",進入睡眠");
26                     Thread.sleep(1000);
27                 } catch (InterruptedException e) {
28                     e.printStackTrace();
29                 }
30                 System.out.println("Thread Name:" + Thread.currentThread().getName() + "睡眠結束");
31                 i++;
32                 System.out.println("I" + i);
33             }
34         }
35     }
36 }

運行結果為:

I:11
Thread Name:Thread-0,進入睡眠
Thread Name:Thread-0睡眠結束
I:12
I:13
Thread Name:Thread-1,進入睡眠
Thread Name:Thread-1睡眠結束
I:14

當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  * yield方法
 3  *
 4  */
 5 public class YieldMethod {
 6     class MyThread extends Thread {
 7         @Override
 8         public void run() {
 9 
10             long beginTime=System.currentTimeMillis();
11             int count=0;
12             for(int i=0;i<50000000;i++){
13                 count = count+(i+1);
14                 Thread.yield();
15             }
16             long endTime=System.currentTimeMillis();
17             System.out.println("用時:"+(endTime-beginTime)+"(ms)");
18 
19         }
20     }
21     public static void main(String[] args) {
22         Thread t1=new YieldMethod().new MyThread();
23         t1.start();
24     }
25 }

結果:

用時:26003(ms)

注釋掉 Thread.yilde(); 之后:

用時:50(ms)

 

對象方法:

1、start()方法

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

2、run()方法

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

3、getId()方法

getId()的作用是取得線程的唯一標識

/**
 * getId方法
 *
 */
public class GetidMethod {
    public static void main(String[] args) {
        Thread t1 = Thread.currentThread();
        System.out.println(t1.getId());
    }
}

輸出:

1

 

4、isAlive()方法

方法isAlive()的功能是判斷當前線程是否處於活動狀態

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

運行結果:

begin:false
end:true
IsAlive:true

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

 System.out.println("IsAlive:" + this.isAlive());

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

 1 public static void main(String[] args) {
 2         Thread t1 = new IsAliveMethod().new MyThread();
 3 
 4         try {
 5             System.out.println("begin:" + t1.isAlive());
 6             t1.start();
 7             t1.sleep(1000);
 8             System.out.println("end:" + t1.isAlive());
 9         } catch (InterruptedException e) {
10             e.printStackTrace();
11         }
12 
13     }
14 }

 

結果:

begin:false
IsAlive:true
end:false

因為mythread對象已經在1秒之內執行完畢。

 

5、join()方法 

 在很多情況下,主線程創建並啟動了線程,如果子線程中葯進行大量耗時運算,主線程往往將早於子線程結束之前結束。這時,如果主線程想等待子線程執行完成之后再結束,比如子線程處理一個數據,主線程要取得這個數據中的值,就要用到join()方法了。方法join()的作用是等待線程對象銷毀。

 

 1 /**
 2  * join方法
 3  *
 4  */
 5 public class JoinMethod extends Thread {
 6     public static void main(String[] args) {
 7         new JoinMethod("JoinMethod").start();
 8         for (int i = 0; i < 10; i++) {
 9             if (i == 5) {
10                 
11                 try {
12                     JoinMethod t1 = new JoinMethod("JoinedMethod main Thread:");
13                     t1.start();
14                     t1.join();
15                 } catch (InterruptedException e) {
16                     e.printStackTrace();
17                 }
18             }
19             System.out.println(Thread.currentThread().getName()+":"+i);
20         }
21     }
22 
23     @Override
24     public void run() {
25         for (int i = 0; i < 5; i++) {
26             System.out.println(getName() + ":\t" + i);
27         }
28     }
29 
30     public JoinMethod(String name) {
31         super(name);
32     }
33 }

 

運行結果:

main:0
JoinMethod:    0
JoinMethod:    1
main:1
JoinMethod:    2
main:2
JoinMethod:    3
JoinMethod:    4
main:3
main:4
JoinedMethod main Thread::    0
JoinedMethod main Thread::    1
JoinedMethod main Thread::    2
JoinedMethod main Thread::    3
JoinedMethod main Thread::    4
main:5
main:6
main:7
main:8
main:9

 

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

main:0
JoinMethod:    0
main:1
JoinMethod:    1
main:2
JoinMethod:    2
main:3
JoinMethod:    3
main:4
JoinMethod:    4
main:5
main:6
main:7
main:8
main:9
JoinedMethod main Thread::    0
JoinedMethod main Thread::    1
JoinedMethod main Thread::    2
JoinedMethod main Thread::    3
JoinedMethod main Thread::    4

 

6、getName()setName() 用來得到或者設置線程名稱

 7、getPriority()setPriority() 用來獲取和設置線程優先級。

8、setDaemon()isDaemon() 用來設置線程是否成為守護線程和判斷線程是否是守護線程。

守護線程和用戶線程的區別在於:守護線程依賴於創建它的線程,而用戶線程則不依賴。舉個簡單的例子:如果在main線程中創建了一個守護線程,當main方法運行完畢之后,守護線程也會隨着消亡。而用戶線程則不會,用戶線程會一直運行直到其運行完畢。在JVM中,像垃圾收集器線程就是守護線程。

 

線程調用不同的方法變為何種狀態呢?


免責聲明!

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



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