一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

線程狀態(tài)的轉(zhuǎn)換(四)

 Lib4Kevin 2015-05-28

一、線程狀態(tài)

 

線程的狀態(tài)轉(zhuǎn)換是線程控制的基礎。線程狀態(tài)總的可分為五大狀態(tài):分別是新建、就緒、運行、等待/阻塞、死亡。各個狀態(tài)描述如下:

 

1、新建狀態(tài):線程對象已經(jīng)創(chuàng)建,還沒有在其上調(diào)用start()方法。

 

2、就緒狀態(tài):當線程有資格運行,但調(diào)度程序還沒有把它選定為運行線程時線程所處的狀態(tài)。當start()方法調(diào)用時,線程首先進入可運行狀態(tài)。在線程運行之后或者從阻塞、等待或睡眠狀態(tài)回來后,也返回到可運行狀態(tài)。

 

3、運行狀態(tài):線程調(diào)度程序從可運行池中選擇一個線程作為當前線程時線程所處的狀態(tài)。這也是線程進入運行狀態(tài)的唯一一種方式。

 

4、等待/阻塞/睡眠狀態(tài):這是線程有資格運行時它所處的狀態(tài)。實際上這個三狀態(tài)組合為一種,其共同點是:線程仍舊是活的,但是當前沒有條件運行。換句話說,它是可運行的,但是如果某件事件出現(xiàn),他可能返回到可運行狀態(tài)。

 

5、死亡狀態(tài):當線程的run()方法完成時就認為它死去。這個線程對象也許是活的,但是,它已經(jīng)不是一個單獨執(zhí)行的線程。線程一旦死亡,就不能復生。如果在一個死去的線程上調(diào)用start()方法,會拋出java.lang.IllegalThreadStateException異常。 

二、阻止線程執(zhí)行

對于線程的阻止,考慮一下三個方面,不考慮IO阻塞的情況:

睡眠;

等待;

因為需要一個對象的鎖定而被阻塞。

 

1、睡眠

Thread.sleep(long millis)Thread.sleep(long millis, int nanos)靜態(tài)方法強制當前正在執(zhí)行的線程休眠(暫停執(zhí)行),以減慢線程。當線程睡眠時,它入睡在某個地方,在蘇醒之前不會返回到可運行狀態(tài)。當睡眠時間到期,則返回到可運行狀態(tài)。

 

線程睡眠的原因:線程執(zhí)行太快,或者需要強制進入下一輪,因為Java規(guī)范不保證合理的輪換。

 

睡眠的實現(xiàn):調(diào)用靜態(tài)方法。

        try {
            Thread.sleep(123);
        } catch (InterruptedException e) {
            e.printStackTrace(); 
        }

 

睡眠的位置:為了讓其他線程有機會執(zhí)行,可以將Thread.sleep()的調(diào)用放線程run()之內(nèi)。這樣才能保證該線程執(zhí)行過程中會睡眠。

 

例如,在前面的例子中,將一個耗時的操作改為睡眠,以減慢線程的執(zhí)行??梢赃@么寫:

 

    public void run() {
        for(int i = 0;i<5;i++){

// 很耗時的操作,用來減慢線程的執(zhí)行
//            for(long k= 0; k <100000000;k++);
            try {
                Thread.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();  .
            }

            System.out.println(this.getName()+" :"+i);
        }
    }

 

運行結(jié)果:

阿三 :0
李四 :0
阿三 :1
阿三 :2
阿三 :3
李四 :1
李四 :2
阿三 :4
李四 :3
李四 :4

Process finished with exit code 0

 

這樣,線程在每次執(zhí)行過程中,總會睡眠3毫秒,睡眠了,其他的線程就有機會執(zhí)行了。

 

注意:

1、線程睡眠是幫助所有線程獲得運行機會的最好方法。

2、線程睡眠到期自動蘇醒,并返回到可運行狀態(tài),不是運行狀態(tài)。sleep()中指定的時間是線程不會運行的最短時間。因此,sleep()方法不能保證該線程睡眠到期后就開始執(zhí)行。

3sleep()是靜態(tài)方法,只能控制當前正在運行的線程。

 

下面給個例子:

/**
*
一個計數(shù)器,計數(shù)到100,在每個數(shù)字之間暫停1秒,每隔10個數(shù)字輸出一個字符串
*
* @author leizhimin 2008-9-14 9:53:49
*/

publicclass MyThreadextends 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


2
、線程的優(yōu)先級和線程讓步yield()

線程的讓步是通過Thread.yield()來實現(xiàn)的。yield()方法的作用是:暫停當前正在執(zhí)行的線程對象,并執(zhí)行其他線程。

 

要理解yield(),必須了解線程的優(yōu)先級的概念。線程總是存在優(yōu)先級,優(yōu)先級范圍在1~10之間。JVM線程調(diào)度程序是基于優(yōu)先級的搶先調(diào)度機制。在大多數(shù)情況下,當前運行的線程優(yōu)先級將大于或等于線程池中任何線程的優(yōu)先級。但這僅僅是大多數(shù)情況。

 

注意:當設計多線程應用程序的時候,一定不要依賴于線程的優(yōu)先級。因為線程調(diào)度優(yōu)先級操作是沒有保障的,只能把線程優(yōu)先級作用作為一種提高程序效率的方法,但是要保證程序不依賴這種操作。

 

當線程池中線程都具有相同的優(yōu)先級,調(diào)度程序的JVM實現(xiàn)自由選擇它喜歡的線程。這時候調(diào)度程序的操作有兩種可能:一是選擇一個線程運行,直到它阻塞或者運行完成為止。二是時間分片,為池內(nèi)的每個線程提供均等的運行機會。

 

設置線程的優(yōu)先級:線程默認的優(yōu)先級是創(chuàng)建它的執(zhí)行線程的優(yōu)先級??梢酝ㄟ^setPriority(int newPriority)更改線程的優(yōu)先級。例如:

        Thread t = new MyThread();
        t.setPriority(8);
        t.start();

線程優(yōu)先級為1~10之間的正整數(shù),JVM從不會改變一個線程的優(yōu)先級。然而,1~10之間的值是沒有保證的。一些JVM可能不能識別10個不同的值,而將這些優(yōu)先級進行每兩個或多個合并,變成少于10個的優(yōu)先級,則兩個或多個優(yōu)先級的線程可能被映射為一個優(yōu)先級。

 

線程默認優(yōu)先級是5,Thread類中有三個常量,定義線程優(yōu)先級范圍:

static int MAX_PRIORITY
         
線程可以具有的最高優(yōu)先級。
static int MIN_PRIORITY
         
線程可以具有的最低優(yōu)先級。
static int NORM_PRIORITY
         
分配給線程的默認優(yōu)先級。

 

3、Thread.yield()方法

 

Thread.yield()方法作用是:暫停當前正在執(zhí)行的線程對象,并執(zhí)行其他線程。

yield()應該做的是讓當前運行線程回到可運行狀態(tài),以允許具有相同優(yōu)先級的其他線程獲得運行機會。因此,使用yield()的目的是讓相同優(yōu)先級的線程之間能適當?shù)妮嗈D(zhuǎn)執(zhí)行。但是,實際中無法保證yield()達到讓步目的,因為讓步的線程還有可能被線程調(diào)度程序再次選中。

結(jié)論:yield()從未導致線程轉(zhuǎn)到等待/睡眠/阻塞狀態(tài)。在大多數(shù)情況下,yield()將導致線程從運行狀態(tài)轉(zhuǎn)到可運行狀態(tài),但有可能沒有效果。

 

4、join()方法

 

Thread的非靜態(tài)方法join()讓一個線程B“加入到另外一個線程A的尾部。在A執(zhí)行完畢之前,B不能工作。例如:

        Thread t = new MyThread();
        t.start();
        t.join();

另外,join()方法還有帶超時限制的重載版本。例如t.join(5000);則讓線程等待5000毫秒,如果超過這個時間,則停止等待,變?yōu)榭蛇\行狀態(tài)。

 

線程的加入join()對線程棧導致的結(jié)果是線程棧發(fā)生了變化,當然這些變化都是瞬時的。下面給示意圖:

 

 

 

小結(jié)

到目前位置,介紹了線程離開運行狀態(tài)的3種方法:

1、調(diào)用Thread.sleep():使當前線程睡眠至少多少毫秒(盡管它可能在指定的時間之前被中斷)。

2、調(diào)用Thread.yield():不能保障太多事情,盡管通常它會讓當前運行線程回到可運行性狀態(tài),使得有相同優(yōu)先級的線程有機會執(zhí)行。

3、調(diào)用join()方法:保證當前線程停止執(zhí)行,直到該線程所加入的線程完成為止。然而,如果它加入的線程沒有存活,則當前線程不需要停止。

 

除了以上三種方式外,還有下面幾種特殊情況可能使線程離開運行狀態(tài):

1、線程的run()方法完成。

2、在對象上調(diào)用wait()方法(不是在線程上調(diào)用)。

3、線程不能在對象上獲得鎖定,它正試圖運行該對象的方法代碼。

4、線程調(diào)度程序可以決定將當前運行狀態(tài)移動到可運行狀態(tài),以便讓另一個線程獲得運行機會,而不需要任何理由。

    本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    国产欧美日韩在线精品一二区| 国产高清一区二区不卡| 欧美精品久久男人的天堂| 在线播放欧美精品一区| 久久偷拍视频免费观看| 欧美日韩国产黑人一区| 国产又色又爽又黄又大| 国产精品日韩欧美一区二区| 国产亚洲精品香蕉视频播放| 殴美女美女大码性淫生活在线播放| 久热久热精品视频在线观看| 日韩午夜老司机免费视频| 亚洲精品国产主播一区| 国产精品激情对白一区二区| 中文字幕不卡欧美在线| 麻豆视传媒短视频在线看| 中日韩免费一区二区三区| 玩弄人妻少妇一区二区桃花| 好吊妞视频免费在线观看| 精品视频一区二区三区不卡| 国产日韩欧美专区一区| 91人妻人澡人人爽人人精品| 1024你懂的在线视频| 中文字幕一二区在线观看| 欧美国产日产在线观看| 日本高清加勒比免费在线| 麻豆国产精品一区二区三区| 亚洲精品美女三级完整版视频| 人妻内射在线二区一区| 欧美国产精品区一区二区三区| 91一区国产中文字幕| 欧美乱妇日本乱码特黄大片| 国产欧美日韩精品自拍| 清纯少妇被捅到高潮免费观看| 91午夜少妇极品福利| 成人欧美精品一区二区三区| 国产成人精品一区在线观看| 日韩不卡一区二区视频| 丝袜视频日本成人午夜视频| 99香蕉精品视频国产版| 老熟女露脸一二三四区|