Java線程:線程狀態(tài)的轉(zhuǎn)換
?
SCJP5學(xué)習(xí)筆記
?
一、線程狀態(tài)
?
線程的狀態(tài)轉(zhuǎn)換是線程控制的基礎(chǔ)。線程狀態(tài)總的可分為五大狀態(tài):分別是生、死、可運(yùn)行、運(yùn)行、等待/阻塞。用一個(gè)圖來(lái)描述如下:
?
1、新?tīng)顟B(tài):線程對(duì)象已經(jīng)創(chuàng)建,還沒(méi)有在其上調(diào)用start()方法。
?
2、可運(yùn)行狀態(tài):當(dāng)線程有資格運(yùn)行,但調(diào)度程序還沒(méi)有把它選定為運(yùn)行線程時(shí)線程所處的狀態(tài)。當(dāng)start()方法調(diào)用時(shí),線程首先進(jìn)入可運(yùn)行狀態(tài)。在線程運(yùn)行之后或者從阻塞、等待或睡眠狀態(tài)回來(lái)后,也返回到可運(yùn)行狀態(tài)。
?
3、運(yùn)行狀態(tài):線程調(diào)度程序從可運(yùn)行池中選擇一個(gè)線程作為當(dāng)前線程時(shí)線程所處的狀態(tài)。這也是線程進(jìn)入運(yùn)行狀態(tài)的唯一一種方式。
?
4、等待/阻塞/睡眠狀態(tài):這是線程有資格運(yùn)行時(shí)它所處的狀態(tài)。實(shí)際上這個(gè)三狀態(tài)組合為一種,其共同點(diǎn)是:線程仍舊是活的,但是當(dāng)前沒(méi)有條件運(yùn)行。換句話說(shuō),它是可運(yùn)行的,但是如果某件事件出現(xiàn),他可能返回到可運(yùn)行狀態(tài)。
?
5、死亡態(tài):當(dāng)線程的run()方法完成時(shí)就認(rèn)為它死去。這個(gè)線程對(duì)象也許是活的,但是,它已經(jīng)不是一個(gè)單獨(dú)執(zhí)行的線程。線程一旦死亡,就不能復(fù)生。 如果在一個(gè)死去的線程上調(diào)用start()方法,會(huì)拋出java.lang.IllegalThreadStateException異常。
?
有關(guān)詳細(xì)狀態(tài)轉(zhuǎn)換圖可以參看本人的“
Java多線程編程總結(jié)
”中的圖
?
二、阻止線程執(zhí)行
對(duì)于線程的阻止,考慮一下三個(gè)方面,不考慮IO阻塞的情況:
睡眠;
等待;
因?yàn)樾枰粋€(gè)對(duì)象的鎖定而被阻塞。
?
1、睡眠
Thread.sleep(long millis)和Thread.sleep(long millis, int nanos)靜態(tài)方法強(qiáng)制當(dāng)前正在執(zhí)行的線程休眠(暫停執(zhí)行),以“減慢線程”。當(dāng)線程睡眠時(shí),它入睡在某個(gè)地方,在蘇醒之前不會(huì)返回到可運(yùn)行狀態(tài)。當(dāng)睡眠時(shí)間到期,則返回到可運(yùn)行狀態(tài)。
?
線程睡眠的原因:線程執(zhí)行太快,或者需要強(qiáng)制進(jìn)入下一輪,因?yàn)镴ava規(guī)范不保證合理的輪換。
?
睡眠的實(shí)現(xiàn):調(diào)用靜態(tài)方法。
??????? try {
??????????? Thread.sleep(123);
??????? } catch (InterruptedException e) {
??????????? e.printStackTrace();?
??????? }
??????????? Thread.sleep(123);
??????? } catch (InterruptedException e) {
??????????? e.printStackTrace();?
??????? }
?
睡眠的位置:為了讓其他線程有機(jī)會(huì)執(zhí)行,可以將Thread.sleep()的調(diào)用放線程run()之內(nèi)。這樣才能保證該線程執(zhí)行過(guò)程中會(huì)睡眠。
?
例如,在前面的例子中,將一個(gè)耗時(shí)的操作改為睡眠,以減慢線程的執(zhí)行。可以這么寫(xiě):
?
??? public void run() {
??????? for(int i = 0;i<5;i++){
??????? for(int i = 0;i<5;i++){
// 很耗時(shí)的操作,用來(lái)減慢線程的執(zhí)行
//??????????? for(long k= 0; k <100000000;k++);
??????????? try {
??????????????? Thread.sleep(3);
??????????? } catch (InterruptedException e) {
??????????????? e.printStackTrace();? .
??????????? }
??????????? System.out.println(this.getName()+" :"+i);
??????? }
??? }
//??????????? for(long k= 0; k <100000000;k++);
??????????? try {
??????????????? Thread.sleep(3);
??????????? } catch (InterruptedException e) {
??????????????? e.printStackTrace();? .
??????????? }
??????????? System.out.println(this.getName()+" :"+i);
??????? }
??? }
?
運(yùn)行結(jié)果:
阿三 :0
李四 :0
阿三 :1
阿三 :2
阿三 :3
李四 :1
李四 :2
阿三 :4
李四 :3
李四 :4
Process finished with exit code 0
李四 :0
阿三 :1
阿三 :2
阿三 :3
李四 :1
李四 :2
阿三 :4
李四 :3
李四 :4
Process finished with exit code 0
?
這樣,線程在每次執(zhí)行過(guò)程中,總會(huì)睡眠3毫秒,睡眠了,其他的線程就有機(jī)會(huì)執(zhí)行了。
?
注意:
1、線程睡眠是幫助所有線程獲得運(yùn)行機(jī)會(huì)的最好方法。
2、線程睡眠到期自動(dòng)蘇醒,并返回到可運(yùn)行狀態(tài),不是運(yùn)行狀態(tài)。sleep()中指定的時(shí)間是線程不會(huì)運(yùn)行的最短時(shí)間。因此,sleep()方法不能保證該線程睡眠到期后就開(kāi)始執(zhí)行。
3、sleep()是靜態(tài)方法,只能控制當(dāng)前正在運(yùn)行的線程。
?
下面給個(gè)例子:
/**
* 一個(gè)計(jì)數(shù)器,計(jì)數(shù)到100,在每個(gè)數(shù)字之間暫停1秒,每隔10個(gè)數(shù)字輸出一個(gè)字符串
*
* @author leizhimin 2008-9-14 9:53:49
*/
public class MyThread extends Thread {
???? public void run() {
???????? for ( int i = 0; i < 100; i++) {
???????????? if ((i) % 10 == 0) {
????????????????System.out.println( "-------" + i);
????????????}
????????????System.out.print(i);
???????????? try {
????????????????Thread.sleep(1);
????????????????System.out.print( "????線程睡眠1毫秒!\n" );
????????????} catch (InterruptedException e) {
????????????????e.printStackTrace();
????????????}
????????}
????}
???? public static void main(String[] args) {
???????? new MyThread().start();
????}
}
* 一個(gè)計(jì)數(shù)器,計(jì)數(shù)到100,在每個(gè)數(shù)字之間暫停1秒,每隔10個(gè)數(shù)字輸出一個(gè)字符串
*
* @author leizhimin 2008-9-14 9:53:49
*/
public class MyThread extends Thread {
???? public void run() {
???????? for ( int i = 0; i < 100; i++) {
???????????? if ((i) % 10 == 0) {
????????????????System.out.println( "-------" + i);
????????????}
????????????System.out.print(i);
???????????? try {
????????????????Thread.sleep(1);
????????????????System.out.print( "????線程睡眠1毫秒!\n" );
????????????} catch (InterruptedException e) {
????????????????e.printStackTrace();
????????????}
????????}
????}
???? public static void main(String[] args) {
???????? new MyThread().start();
????}
}
?
-------0
0????線程睡眠1毫秒!
1????線程睡眠1毫秒!
2????線程睡眠1毫秒!
3????線程睡眠1毫秒!
4????線程睡眠1毫秒!
5????線程睡眠1毫秒!
6????線程睡眠1毫秒!
7????線程睡眠1毫秒!
8????線程睡眠1毫秒!
9????線程睡眠1毫秒!
-------10
10????線程睡眠1毫秒!
11????線程睡眠1毫秒!
12????線程睡眠1毫秒!
13????線程睡眠1毫秒!
14????線程睡眠1毫秒!
15????線程睡眠1毫秒!
16????線程睡眠1毫秒!
17????線程睡眠1毫秒!
18????線程睡眠1毫秒!
19????線程睡眠1毫秒!
-------20
20????線程睡眠1毫秒!
21????線程睡眠1毫秒!
22????線程睡眠1毫秒!
23????線程睡眠1毫秒!
24????線程睡眠1毫秒!
25????線程睡眠1毫秒!
26????線程睡眠1毫秒!
27????線程睡眠1毫秒!
28????線程睡眠1毫秒!
29????線程睡眠1毫秒!
-------30
30????線程睡眠1毫秒!
31????線程睡眠1毫秒!
32????線程睡眠1毫秒!
33????線程睡眠1毫秒!
34????線程睡眠1毫秒!
35????線程睡眠1毫秒!
36????線程睡眠1毫秒!
37????線程睡眠1毫秒!
38????線程睡眠1毫秒!
39????線程睡眠1毫秒!
-------40
40????線程睡眠1毫秒!
41????線程睡眠1毫秒!
42????線程睡眠1毫秒!
43????線程睡眠1毫秒!
44????線程睡眠1毫秒!
45????線程睡眠1毫秒!
46????線程睡眠1毫秒!
47????線程睡眠1毫秒!
48????線程睡眠1毫秒!
49????線程睡眠1毫秒!
-------50
50????線程睡眠1毫秒!
51????線程睡眠1毫秒!
52????線程睡眠1毫秒!
53????線程睡眠1毫秒!
54????線程睡眠1毫秒!
55????線程睡眠1毫秒!
56????線程睡眠1毫秒!
57????線程睡眠1毫秒!
58????線程睡眠1毫秒!
59????線程睡眠1毫秒!
-------60
60????線程睡眠1毫秒!
61????線程睡眠1毫秒!
62????線程睡眠1毫秒!
63????線程睡眠1毫秒!
64????線程睡眠1毫秒!
65????線程睡眠1毫秒!
66????線程睡眠1毫秒!
67????線程睡眠1毫秒!
68????線程睡眠1毫秒!
69????線程睡眠1毫秒!
-------70
70????線程睡眠1毫秒!
71????線程睡眠1毫秒!
72????線程睡眠1毫秒!
73????線程睡眠1毫秒!
74????線程睡眠1毫秒!
75????線程睡眠1毫秒!
76????線程睡眠1毫秒!
77????線程睡眠1毫秒!
78????線程睡眠1毫秒!
79????線程睡眠1毫秒!
-------80
80????線程睡眠1毫秒!
81????線程睡眠1毫秒!
82????線程睡眠1毫秒!
83????線程睡眠1毫秒!
84????線程睡眠1毫秒!
85????線程睡眠1毫秒!
86????線程睡眠1毫秒!
87????線程睡眠1毫秒!
88????線程睡眠1毫秒!
89????線程睡眠1毫秒!
-------90
90????線程睡眠1毫秒!
91????線程睡眠1毫秒!
92????線程睡眠1毫秒!
93????線程睡眠1毫秒!
94????線程睡眠1毫秒!
95????線程睡眠1毫秒!
96????線程睡眠1毫秒!
97????線程睡眠1毫秒!
98????線程睡眠1毫秒!
99????線程睡眠1毫秒!
Process finished with exit code 0
0????線程睡眠1毫秒!
1????線程睡眠1毫秒!
2????線程睡眠1毫秒!
3????線程睡眠1毫秒!
4????線程睡眠1毫秒!
5????線程睡眠1毫秒!
6????線程睡眠1毫秒!
7????線程睡眠1毫秒!
8????線程睡眠1毫秒!
9????線程睡眠1毫秒!
-------10
10????線程睡眠1毫秒!
11????線程睡眠1毫秒!
12????線程睡眠1毫秒!
13????線程睡眠1毫秒!
14????線程睡眠1毫秒!
15????線程睡眠1毫秒!
16????線程睡眠1毫秒!
17????線程睡眠1毫秒!
18????線程睡眠1毫秒!
19????線程睡眠1毫秒!
-------20
20????線程睡眠1毫秒!
21????線程睡眠1毫秒!
22????線程睡眠1毫秒!
23????線程睡眠1毫秒!
24????線程睡眠1毫秒!
25????線程睡眠1毫秒!
26????線程睡眠1毫秒!
27????線程睡眠1毫秒!
28????線程睡眠1毫秒!
29????線程睡眠1毫秒!
-------30
30????線程睡眠1毫秒!
31????線程睡眠1毫秒!
32????線程睡眠1毫秒!
33????線程睡眠1毫秒!
34????線程睡眠1毫秒!
35????線程睡眠1毫秒!
36????線程睡眠1毫秒!
37????線程睡眠1毫秒!
38????線程睡眠1毫秒!
39????線程睡眠1毫秒!
-------40
40????線程睡眠1毫秒!
41????線程睡眠1毫秒!
42????線程睡眠1毫秒!
43????線程睡眠1毫秒!
44????線程睡眠1毫秒!
45????線程睡眠1毫秒!
46????線程睡眠1毫秒!
47????線程睡眠1毫秒!
48????線程睡眠1毫秒!
49????線程睡眠1毫秒!
-------50
50????線程睡眠1毫秒!
51????線程睡眠1毫秒!
52????線程睡眠1毫秒!
53????線程睡眠1毫秒!
54????線程睡眠1毫秒!
55????線程睡眠1毫秒!
56????線程睡眠1毫秒!
57????線程睡眠1毫秒!
58????線程睡眠1毫秒!
59????線程睡眠1毫秒!
-------60
60????線程睡眠1毫秒!
61????線程睡眠1毫秒!
62????線程睡眠1毫秒!
63????線程睡眠1毫秒!
64????線程睡眠1毫秒!
65????線程睡眠1毫秒!
66????線程睡眠1毫秒!
67????線程睡眠1毫秒!
68????線程睡眠1毫秒!
69????線程睡眠1毫秒!
-------70
70????線程睡眠1毫秒!
71????線程睡眠1毫秒!
72????線程睡眠1毫秒!
73????線程睡眠1毫秒!
74????線程睡眠1毫秒!
75????線程睡眠1毫秒!
76????線程睡眠1毫秒!
77????線程睡眠1毫秒!
78????線程睡眠1毫秒!
79????線程睡眠1毫秒!
-------80
80????線程睡眠1毫秒!
81????線程睡眠1毫秒!
82????線程睡眠1毫秒!
83????線程睡眠1毫秒!
84????線程睡眠1毫秒!
85????線程睡眠1毫秒!
86????線程睡眠1毫秒!
87????線程睡眠1毫秒!
88????線程睡眠1毫秒!
89????線程睡眠1毫秒!
-------90
90????線程睡眠1毫秒!
91????線程睡眠1毫秒!
92????線程睡眠1毫秒!
93????線程睡眠1毫秒!
94????線程睡眠1毫秒!
95????線程睡眠1毫秒!
96????線程睡眠1毫秒!
97????線程睡眠1毫秒!
98????線程睡眠1毫秒!
99????線程睡眠1毫秒!
Process finished with exit code 0
2、線程的優(yōu)先級(jí)和線程讓步y(tǒng)ield()
線程的讓步是通過(guò)Thread.
yield
()來(lái)實(shí)現(xiàn)的。yield()方法的作用是:暫停當(dāng)前正在執(zhí)行的線程對(duì)象,并執(zhí)行其他線程。
?
要理解yield(),必須了解線程的優(yōu)先級(jí)的概念。線程總是存在優(yōu)先級(jí),優(yōu)先級(jí)范圍在1~10之間。JVM線程調(diào)度程序是基于優(yōu)先級(jí)的搶先調(diào)度機(jī)制。在大多數(shù)情況下,當(dāng)前運(yùn)行的線程優(yōu)先級(jí)將大于或等于線程池中任何線程的優(yōu)先級(jí)。但這僅僅是大多數(shù)情況。
?
注意:當(dāng)設(shè)計(jì)多線程應(yīng)用程序的時(shí)候,一定不要依賴于線程的優(yōu)先級(jí)。因?yàn)榫€程調(diào)度優(yōu)先級(jí)操作是沒(méi)有保障的,只能把線程優(yōu)先級(jí)作用作為一種提高程序效率的方法,但是要保證程序不依賴這種操作。
?
當(dāng)線程池中線程都具有相同的優(yōu)先級(jí),調(diào)度程序的JVM實(shí)現(xiàn)自由選擇它喜歡的線程。這時(shí)候調(diào)度程序的操作有兩種可能:一是選擇一個(gè)線程運(yùn)行,直到它阻塞或者運(yùn)行完成為止。二是時(shí)間分片,為池內(nèi)的每個(gè)線程提供均等的運(yùn)行機(jī)會(huì)。
?
設(shè)置線程的優(yōu)先級(jí):線程默認(rèn)的優(yōu)先級(jí)是創(chuàng)建它的執(zhí)行線程的優(yōu)先級(jí)。可以通過(guò)setPriority(int newPriority)更改線程的優(yōu)先級(jí)。例如:
??????? Thread t = new MyThread();
??????? t.setPriority(8);
??????? t.start();
??????? t.setPriority(8);
??????? t.start();
線程優(yōu)先級(jí)為1~10之間的正整數(shù),JVM從不會(huì)改變一個(gè)線程的優(yōu)先級(jí)。然而,1~10之間的值是沒(méi)有保證的。一些JVM可能不能識(shí)別10個(gè)不同的值,而將這些優(yōu)先級(jí)進(jìn)行每?jī)蓚€(gè)或多個(gè)合并,變成少于10個(gè)的優(yōu)先級(jí),則兩個(gè)或多個(gè)優(yōu)先級(jí)的線程可能被映射為一個(gè)優(yōu)先級(jí)。
?
線程默認(rèn)優(yōu)先級(jí)是5,Thread類中有三個(gè)常量,定義線程優(yōu)先級(jí)范圍:
static int MAX_PRIORITY
????????? 線程可以具有的最高優(yōu)先級(jí)。
static int MIN_PRIORITY
????????? 線程可以具有的最低優(yōu)先級(jí)。
static int NORM_PRIORITY
????????? 分配給線程的默認(rèn)優(yōu)先級(jí)。
????????? 線程可以具有的最高優(yōu)先級(jí)。
static int MIN_PRIORITY
????????? 線程可以具有的最低優(yōu)先級(jí)。
static int NORM_PRIORITY
????????? 分配給線程的默認(rèn)優(yōu)先級(jí)。
?
3、Thread.yield()方法
?
Thread.yield()方法作用是:暫停當(dāng)前正在執(zhí)行的線程對(duì)象,并執(zhí)行其他線程。
yield()應(yīng)該做的是讓當(dāng)前運(yùn)行線程回到可運(yùn)行狀態(tài),以允許具有相同優(yōu)先級(jí)的其他線程獲得運(yùn)行機(jī)會(huì)。因此,使用yield()的目的是讓相同優(yōu)先級(jí)的線程之間能適當(dāng)?shù)妮嗈D(zhuǎn)執(zhí)行。但是,實(shí)際中無(wú)法保證yield()達(dá)到讓步目的,因?yàn)樽尣降木€程還有可能被線程調(diào)度程序再次選中。
結(jié)論:yield()從未導(dǎo)致線程轉(zhuǎn)到等待/睡眠/阻塞狀態(tài)。在大多數(shù)情況下,yield()將導(dǎo)致線程從運(yùn)行狀態(tài)轉(zhuǎn)到可運(yùn)行狀態(tài),但有可能沒(méi)有效果。
?
4、join()方法
?
這個(gè)方法講的不是很清楚,下面有個(gè)實(shí)例
Thread的非靜態(tài)方法join()讓一個(gè)線程B“加入”到另外一個(gè)線程A的尾部。在A執(zhí)行完畢之前,B不能工作。例如:
??????? Thread t = new MyThread();
??????? t.start();
??????? t.join();
??????? t.start();
??????? t.join();
另外,join()方法還有帶超時(shí)限制的重載版本。 例如t.join(5000);則讓線程等待5000毫秒,如果超過(guò)這個(gè)時(shí)間,則停止等待,變?yōu)榭蛇\(yùn)行狀態(tài)。
?
線程的加入join()對(duì)線程棧導(dǎo)致的結(jié)果是線程棧發(fā)生了變化,當(dāng)然這些變化都是瞬時(shí)的。下面給示意圖:
?
?
?
小結(jié)
到目前位置,介紹了線程離開(kāi)運(yùn)行狀態(tài)的3種方法:
1、調(diào)用Thread.sleep():使當(dāng)前線程睡眠至少多少毫秒(盡管它可能在指定的時(shí)間之前被中斷)。
2、調(diào)用Thread.yield():不能保障太多事情,盡管通常它會(huì)讓當(dāng)前運(yùn)行線程回到可運(yùn)行性狀態(tài),使得有相同優(yōu)先級(jí)的線程有機(jī)會(huì)執(zhí)行。
3、調(diào)用join()方法:保證當(dāng)前線程停止執(zhí)行,直到該線程所加入的線程完成為止。然而,如果它加入的線程沒(méi)有存活,則當(dāng)前線程不需要停止。
?
除了以上三種方式外,還有下面幾種特殊情況可能使線程離開(kāi)運(yùn)行狀態(tài):
1、線程的run()方法完成。
2、在對(duì)象上調(diào)用wait()方法(不是在線程上調(diào)用)。
3、線程不能在對(duì)象上獲得鎖定,它正試圖運(yùn)行該對(duì)象的方法代碼。
4、線程調(diào)度程序可以決定將當(dāng)前運(yùn)行狀態(tài)移動(dòng)到可運(yùn)行狀態(tài),以便讓另一個(gè)線程獲得運(yùn)行機(jī)會(huì),而不需要任何理由。
?
?
上面的join方法講的不是很清楚是,所以在下面找了一個(gè)例子。
public class JoinThread extends Thread{
? ? ?public JoinThread(String name){
? ? ? ? ? ?super(name);
? ? ?}
? ? ?
? ? ?public void run(){
? ? ? ? ? ?for(int i=0; i<10; i++){
? ? ? ? ? ? ? ? ?for(long k=0; k<100000000; k++){}
? ? ? ? ? ? ? ? ?System.out.println(this.getName() + ": " + i);
? ? ? ? ? ?}
? ? ?}
? ? ?
? ? ?public static void main(String[] args){
? ? ? ? ? ?Thread t1 = new JoinThread("AA AA");
? ? ? ? ? ?t1.start();
? ? ? ? ? ?try{
? ? ? ? ? ? ? ? ?t1.join(1000); ? ? ? ? ? ? ? ? //Join在這里~
? ? ? ? ? ?} catch(InterruptedException e) {
? ? ? ? ? ? ? ? ?e.printStackTrace();
? ? ? ? ? ?} ? ? ?
? ? ? ? ? ?System.out.println("over");
? ? ?}
}
然后輸出的結(jié)果是:
AA AA: 0
AA AA: 1
over
AA AA: 2
AA AA: 3
AA AA: 4
AA AA: 5
AA AA: 6
AA AA: 7
AA AA: 8
AA AA: 9
但是如果把 t.join(1000) 改成 t.join() 的話輸出結(jié)果會(huì)變成:
AA AA: 0
AA AA: 1
AA AA: 2
AA AA: 3
AA AA: 4
AA AA: 5
AA AA: 6
AA AA: 7
AA AA: 8
AA AA: 9
over
這樣子就很明顯了,t.join(int wait_time);后面的代碼想要執(zhí)行需要滿足以下條件之一:
1、線程t死了;
2、等待時(shí)間超過(guò)wait_time;
如果沒(méi)有指定wait_time就只能等線程t死了才行了···
? ? ?public JoinThread(String name){
? ? ? ? ? ?super(name);
? ? ?}
? ? ?
? ? ?public void run(){
? ? ? ? ? ?for(int i=0; i<10; i++){
? ? ? ? ? ? ? ? ?for(long k=0; k<100000000; k++){}
? ? ? ? ? ? ? ? ?System.out.println(this.getName() + ": " + i);
? ? ? ? ? ?}
? ? ?}
? ? ?
? ? ?public static void main(String[] args){
? ? ? ? ? ?Thread t1 = new JoinThread("AA AA");
? ? ? ? ? ?t1.start();
? ? ? ? ? ?try{
? ? ? ? ? ? ? ? ?t1.join(1000); ? ? ? ? ? ? ? ? //Join在這里~
? ? ? ? ? ?} catch(InterruptedException e) {
? ? ? ? ? ? ? ? ?e.printStackTrace();
? ? ? ? ? ?} ? ? ?
? ? ? ? ? ?System.out.println("over");
? ? ?}
}
然后輸出的結(jié)果是:
AA AA: 0
AA AA: 1
over
AA AA: 2
AA AA: 3
AA AA: 4
AA AA: 5
AA AA: 6
AA AA: 7
AA AA: 8
AA AA: 9
但是如果把 t.join(1000) 改成 t.join() 的話輸出結(jié)果會(huì)變成:
AA AA: 0
AA AA: 1
AA AA: 2
AA AA: 3
AA AA: 4
AA AA: 5
AA AA: 6
AA AA: 7
AA AA: 8
AA AA: 9
over
這樣子就很明顯了,t.join(int wait_time);后面的代碼想要執(zhí)行需要滿足以下條件之一:
1、線程t死了;
2、等待時(shí)間超過(guò)wait_time;
如果沒(méi)有指定wait_time就只能等線程t死了才行了···
本文出自 “ 熔 巖 ” 博客: http://lavasoft.blog.51cto.com/62575/99153
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
