之前有簡單介紹過java多線程的使用,已經Thread類和Runnable類,為了更好地理解多線程,本文就Thread進行詳細的分析。
start()
我們先來看看API中對于該方法的介紹:
使該線程開始執行;Java 虛擬機調用該線程的 run 方法。
結果是兩個線程并發地運行;當前線程(從調用返回給 start 方法)和另一個線程(執行其 run 方法)。
多次啟動一個線程是非法的。特別是當線程已經結束執行后,不能再重新啟動。
用start方法來啟動線程,真正實現了多線程運行,這時無需等待run方法體代碼執行完畢而直接繼續執行下面的代碼。通過調用Thread類的 start()方法來啟動一個線程,這時此線程處于就緒(可運行)狀態,并沒有運行,一旦得到cpu時間片,就開始執行run()方法,這里方法 run()稱為線程體,它包含了要執行的這個線程的內容,Run方法運行結束,此線程隨即終止。
start方法是開啟線程的方法,使用后java會創建一個新的線程執行run里的方法。這是一個小demo:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
for ( int i= 0 ;i< 3 ;i++){ Thread t= new Thread( new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName()+ " start" ); try { Thread.sleep( 1000 ); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+ " end" ); } }); t.start(); } System.out.println( "it is over" ); |
執行結果:
it is over
Thread-1 start
Thread-0 start
Thread-2 start
Thread-0 end
Thread-1 end
Thread-2 end
由于多線程是有隨機性的,所以每次的結果可能都不一樣,這一點也是我們需要注意的,線程的執行順序和調用順序并不一致。
run()
run方法就是調用Thread設置的Runnable的run方法,將上面的demo進行修改:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
for ( int i= 0 ;i< 3 ;i++){ Thread t= new Thread( new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName()+ " start" ); try { Thread.sleep( 1000 ); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+ " end" ); } }); t.run(); } System.out.println( "it is over" ); |
執行結果:
main start
main end
main start
main end
main start
main end
it is over
run方法的直接結果和start有很大的差別,完全是按順序執行,并沒有開啟新線程。
stop()
stop方法是強制停止線程的執行,是非安全的,不要使用此方法。在調用stop時, 會對鎖定的資源進行釋放,但這種釋放是非一致的,容易引起程序問題。如果想要控制線程的停止,可以使用自定義變量來判斷或者isInterrupted()方法:
1
2
3
4
5
6
7
8
9
|
class Thread1 extends Thread { @Override public void run() { //判斷線程體是否運行 while (!isInterrupted()) { // Do Something } } } |
interrupt()
interrupt的作用是通知線程,你已經被中斷的,但具體的中斷執行需要在線程自定義處理,甚至你可以不理會繼續執行。具體的中孤單是會線程執行join、wait、sleep方法時,拋出InterruptedException。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
Thread t1 = new Thread( new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName()+ " start" ); try { for ( int i= 0 ;i< 100000 ;i++){ System.out.println(i+ "" ); Thread.sleep( 1 ); } } catch (InterruptedException e) { System.out.println( "the thread is interrupted" ); //可以在這里做資源釋放,日志記錄等 e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+ " end" ); } }); t1.start(); Thread.sleep( 100 ); t1.interrupt(); |
執行結果:
1
2
3
4
5
6
7
8
9
10
|
65 66 67 68 the thread is interrupted java.lang.InterruptedException: sleep interrupted Thread- 0 end at java.lang.Thread.sleep(Native Method) at com.wk.aqi.act.Test$ 1 .run(Test.java: 23 ) at java.lang.Thread.run(Thread.java: 745 ) |
isInterrupted()
判斷線程是否中斷,在執行上面的interrupt方法后,會return true。
setPriority(int newPriority)和getPriority()
設置線程的優先級和獲取線程的優先級,cpu分配的資源給側重給priority高的線程。
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
|
Thread t1 = new Thread( new Runnable() { @Override public void run() { long t = System.currentTimeMillis(); System.out.println(Thread.currentThread().getName()+ " start" ); for ( int i= 0 ;i< 1000 ;i++){ try { Thread.sleep( 1 ); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } System.out.println(Thread.currentThread().getName()+ " t1 end " +(System.currentTimeMillis()-t)); } }); Thread t2 = new Thread( new Runnable() { @Override public void run() { long t = System.currentTimeMillis(); System.out.println(Thread.currentThread().getName()+ " start" ); for ( int i= 0 ;i< 1000 ;i++){ try { Thread.sleep( 1 ); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } System.out.println(Thread.currentThread().getName()+ " t2 end " +(System.currentTimeMillis()-t)); } }); t1.setPriority( 10 ); t2.setPriority( 1 ); t2.start(); t1.start(); |
執行結果:
1
2
3
4
|
Thread- 0 start Thread- 1 start Thread- 0 t1 end 1357 Thread- 1 t2 end 1371 |
在優先級一樣的情況下,t1和t2是幾乎同時完成的,在優先級不一樣的情況,有明顯的差別。
getName()
比較簡單,獲取線程的名稱。
join()和join(long millis)
jion方法的作用是等待線程執行完成,join(long millis)可以設置最長等待時間。比如主線程需要等待子線程完成,獲取子線程的結果后才能繼續往下執行,這時候就可以使用join方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
Thread t1 = new Thread( new Runnable() { @Override public void run() { long t = System.currentTimeMillis(); System.out.println(Thread.currentThread().getName()+ " start" ); try { Thread.sleep( 1000 ); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+ " t1 end " +(System.currentTimeMillis()-t)); } }); t1.start(); t1.join(); System.out.println( "等待t1執行完,再執行" ); |
執行結果:
1
2
3
|
Thread- 0 start Thread- 0 t1 end 1001 等待t1執行完,再執行 |
總結
以上就是本文關于java多線程Thread的實現方法代碼詳解的全部內容,希望對大家有所幫助。感興趣的朋友可以繼續參閱本站其他相關專題,如有不足之處,歡迎留言指出。
原文鏈接:https://segmentfault.com/a/1190000012213171