亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

java學習筆記15--多線程編程基礎2

2019-11-14 23:31:54
字體:
來源:轉載
供稿:網友
java學習筆記15--多線程編程基礎2

本文地址:http://www.49028c.com/archimedes/p/java-study-note15.html,轉載請注明源地址。

線程的生命周期

1、線程的生命周期

線程從產生到消亡的過程

一個線程在任何時刻都處于某種線程狀態(thread state)

線程生命周期狀態圖

誕生狀態

線程剛剛被創建

就緒狀態

線程的 start 方法已被執行

線程已準備好運行

運行狀態

處理機分配給了線程,線程正在運行

阻塞狀態(Blocked)

在線程發出輸入/輸出請求且必須等待其返回

遇到用synchronized標記的方法而未獲得其監視器暫時不能進入執行時

休眠狀態(Sleeping)

執行sleep方法而進入休眠

死亡狀態

線程已完成或退出

2、死鎖問題

死鎖

線程在運行過程中,其中某個步驟往往需要滿足一些條件才能繼續進行下去,如果這個條件不能滿足,線程將在這個步驟上出現阻塞

線程A可能會陷于對線程B的等待,而線程B同樣陷于對線程C的等待,依次類推,整個等待鏈最后又可能回到線程A。如此一來便陷入一個彼此等待的輪回中,任何線程都動彈不得,此即所謂死鎖(deadlock)

對于死鎖問題,關鍵不在于出現問題后調試,而是在于預防

設想一個游戲,規則為3個人站在三角形的三個頂點的位置上,三個邊上放著三個球,如圖所示。每個人都必須先拿到自己左手邊的球,才能再拿到右手邊的球,兩手都有球之后,才能夠把兩個球都放下

創建3個線程模擬3個游戲者的行為。

class Balls {    boolean flag0 = false;    //0號球的標志變量,true表示已被人拿,false表示未被任何人拿    boolean flag1 = false;    //1號球的標志變量    boolean flag2 = false;    //2號球的標志變量}class Player0 extends Thread {    //0號游戲者的類    PRivate Balls ball;    public Player0(Balls b) {        this.ball = b;    }    public void run() {        while(true) {            while(ball.flag1 == true){}    //如果1號球已被拿走,則等待            ball.flag1 = true;    //拿起1號球            while(ball.flag0 == true){}    //如果0號球已被拿走,則等待            if(ball.flag1 == true && ball.flag0 == false) {                ball.flag0 = true;    //拿起0號球                System.out.println("Player0 has got two balls!");                ball.flag1 = false;    //放下1號球                ball.flag0 = false;    //放下0號球                try {                    sleep(1);        //放下后休息1ms                } catch (Exception e) {                                    }            }        }    }}class Player1 extends Thread {    //1號游戲者的類    private Balls ball;    public Player1(Balls b) {        this.ball = b;    }    public void run() {        while(true) {            while(ball.flag0 == true){}            ball.flag0 = true;            while(ball.flag1 == true){}            if(ball.flag0 == true && ball.flag1 == false) {                ball.flag1 = true;                System.out.println("Player0 has got two balls!");                ball.flag0 = false;                ball.flag1 = false;                try {                    sleep(1);                } catch (Exception e) {                                    }            }        }    }}class Player2 extends Thread {    //2號游戲者的類    private Balls ball;    public Player2(Balls b) {        this.ball = b;    }    public void run() {        while(true) {            while(ball.flag2 == true){}            ball.flag2 = true;            while(ball.flag1 == true){}            if(ball.flag2 == true && ball.flag1 == false) {                ball.flag1 = true;                System.out.println("Player0 has got two balls!");                ball.flag2 = false;                ball.flag1 = false;                try {                    sleep(1);                } catch (Exception e) {                                    }            }        }    }}public class playball {    public static void main(String[] args) {        Balls ball = new Balls();    //創建一個球類對象        Player0 p0 = new Player0(ball);    //創建0號游戲者        Player1 p1 = new Player1(ball);    //創建1號游戲者        Player2 p2 = new Player2(ball);    //創建2號游戲者        p0.start();    //啟動0號游戲者        p1.start();    //啟動1號游戲者        p2.start();    //啟動2號游戲者    }}

運行結果:

若干次后將陷入死鎖,不再有輸出信息,即任何人都不能再同時擁有兩側的球

程序說明:

如果剛好3個人都拿到了左手邊的球,都等待那右手邊的球,則因為誰都不能放手,則這3個線程都將陷入無止盡的等待當中,這就構成了死鎖

為了便于觀察死鎖發生的條件,我們在每個游戲者放下兩邊的球后增加了sleep語句

為了避免死鎖,需要修改游戲規則,使每個人都只能先搶到兩側中號比較小的球,才能拿另一只球,這樣就不會再出現死鎖現象

3、控制線程的生命

結束線程的生命

用stop方法可以結束線程的生命

但如果一個線程正在操作共享數據段,操作過程沒有完成就用stop結束的話,將會導致數據的不完整,因此并不提倡使用此方法

通常,可通過控制run方法中循環條件的方式來結束一個線程

線程不斷顯示遞增整數,按下回車鍵則停止執行:

class TestThread1 extends Thread {    private boolean flag = true;    public void stopme() {    //在此方法中控制循環條件        flag = false;    }    public void run() {        int i = 0;        while(flag) {            System.out.println(i++);  //如果flag為真則一直顯示遞增整數        }    }}public class ext8_12 {    public static void main(String[] args)  throws IOException{        TestThread1 t = new TestThread1();        t.start();        new BufferedReader(new InputStreamReader(System.in)).readLine();    //等待鍵盤輸入        t.stopme();        //調用stopme方法結束t線程    }}

運行效果為按下回車鍵后則停止顯示

線程的優先級

線程調度

在單CPU的系統中,多個線程需要共享CPU,在任何時間點上實際只能有一個線程在運行

控制多個線程在同一個CPU上以某種順序運行稱為線程調度

Java虛擬機支持一種非常簡單的、確定的調度算法,叫做固定優先級算法。這個算法基于線程的優先級對其進行調度

線程的優先級

每個Java線程都有一個優先級,其范圍都在1和10之間。默認情況下,每個線程的優先級都設置為5

在線程A運行過程中創建的新的線程對象B,初始狀態具有和線程A相同的優先級

如果A是個后臺線程,則B也是個后臺線程

可在線程創建之后的任何時候,通過setPriority(int priority)方法改變其原來的優先級

基于線程優先級的線程調度

具有較高優先級的線程比優先級較低的線程優先執行

對具有相同優先級的線程,Java的處理是隨機的

底層操作系統支持的優先級可能要少于10個,這樣會造成一些混亂。因此,只能將優先級作為一種很粗略的工具使用。最后的控制可以通過明智地使用yield()函數來完成

我們只能基于效率的考慮來使用線程優先級,而不能依靠線程優先級來保證算法的正確性

假設某線程正在運行,則只有出現以下情況之一,才會使其暫停運行

一個具有更高優先級的線程變為就緒狀態(Ready);

由于輸入/輸出(或其他一些原因)、調用sleep、wait、yield方法使其發生阻塞;

對于支持時間分片的系統,時間片的時間期滿

例子:創建兩個具有不同優先級的線程,都從1遞增到400000,每增加50000顯示一次
class TestThread2 extends Thread {    private int tick = 1;    private int num;    public TestThread2(int i) {        this.num = i;    }    public void run() {        while(tick < 400000) {            tick++;            if((tick % 50000) == 0) {    //每隔50000進行顯示                System.out.println("Thread#" + num +",tick=" + tick);                yield();    //放棄執行權            }        }    }}public class ext8_13 {    public static void main(String[] args) {        TestThread2[] runners = new TestThread2[2];        for(int i = 0; i < 2; i++)    runners[i] = new TestThread2(i);        runners[0].setPriority(2);        runners[1].setPriority(3);        for(int i = 0; i < 2; i++)            runners[i].start();    }}

運行結果如下:

Thread #1, tick = 50000

Thread #1, tick = 100000

Thread #1, tick = 150000

Thread #1, tick = 200000

Thread #1, tick = 250000

Thread #1, tick = 300000

Thread #1, tick = 350000

Thread #1, tick = 400000

Thread #0, tick = 50000

Thread #0, tick = 100000

Thread #0, tick = 150000

Thread #0, tick = 200000

Thread #0, tick = 250000

Thread #0, tick = 300000

Thread #0, tick = 350000

Thread #0, tick = 400000

結果說明:

具有較高優先級的線程1一直運行到結束,具有較低優先級的線程0才開始運行

雖然具有較高優先級的線程1調用了yield方法放棄CPU資源,允許線程0進行爭奪,但馬上又被線程1搶奪了回去,所以有沒有yield方法都沒什么區別

如果在yield方法后增加一行sleep語句,讓線程1暫時放棄一下在CPU上的運行,哪怕是1毫秒,則線程0也可以有機會被調度。修改后的run方法如下:

    public void run() {        while(tick < 400000) {            tick++;            if((tick % 50000) == 0) {    //每隔50000進行顯示                System.out.println("Thread#" + num +",tick=" + tick);                yield();    //放棄執行權                try {                    sleep(1);                } catch(Exception e) {                                    }            }        }    }

運行結果如下:

Thread #1, tick = 50000

Thread #1, tick = 100000

Thread #1, tick = 150000

Thread #1, tick = 200000

Thread #0, tick = 50000

Thread #1, tick = 250000

Thread #1, tick = 300000

Thread #0, tick = 100000

Thread #1, tick = 350000

Thread #1, tick = 400000

Thread #0, tick = 150000

Thread #0, tick = 200000

Thread #0, tick = 250000

Thread #0, tick = 300000

Thread #0, tick = 350000

Thread #0, tick = 400000

說明

具有較低優先權的線程0在線程1沒有執行完畢前也獲得了一部分執行,但線程1還是優先完成了執行

Java虛擬機本身并不支持某個線程搶奪另一個正在執行的具有同等優先級線程的執行權

通常,我們在一個線程內部插入yield()語句,這個方法會使正在運行的線程暫時放棄執行,這是具有同樣優先級的線程就有機會獲得調度開始運行,但較低優先級的線程仍將被忽略不參加調度

您還可能感興趣:

java學習筆記系列:

java學習筆記14--多線程編程基礎1

java學習筆記13--反射機制與動態代理

java學習筆記12--異常處理

java學習筆記11--集合總結

java學習筆記10--泛型總結

java學習筆記9--內部類總結

java學習筆記8--接口總結

java學習筆記7--抽象類與抽象方法

java學習筆記6--類的繼承、Object類

java學習筆記5--類的方法

java學習筆記4--對象的初始化與回收

java學習筆記3--類與對象的基礎

java學習筆記2--數據類型、數組

java學習筆記1--開發環境平臺總結


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产精品免费一区| 亚洲欧美一区二区三区情侣bbw| 欧美老女人xx| 日韩精品一二三四区| 欧美成人黑人xx视频免费观看| 日韩av在线网址| 久久国产精品久久久久久久久久| 亚洲国产精品小视频| 国产深夜精品福利| 国内精品久久久久久| 亚洲在线视频福利| 欧美日韩另类视频| 亚洲国产黄色片| 伊人久久久久久久久久久| 国产成人精品网站| 欧美插天视频在线播放| 日本中文字幕不卡免费| 亚洲国产另类久久精品| 久久九九热免费视频| 欧美性xxxx极品hd欧美风情| 亚洲国产欧美一区二区三区同亚洲| 亚洲精品v欧美精品v日韩精品| 国产精品永久在线| 欧美在线观看日本一区| 欧美三级xxx| 欧美激情视频免费观看| 欧美日韩美女在线观看| 欧美孕妇性xx| 国产亚洲精品一区二555| 久久中国妇女中文字幕| 欧美性猛交xxxx乱大交蜜桃| 欧美裸体男粗大视频在线观看| 精品国产网站地址| 欧美成人午夜影院| 亚洲精品一区中文字幕乱码| 国产精品视频男人的天堂| 亚洲网站在线观看| 国产一区二区三区高清在线观看| 色伦专区97中文字幕| 国产精品电影在线观看| 日韩美女视频免费在线观看| 亚洲四色影视在线观看| 热草久综合在线| 亚洲成av人乱码色午夜| 91久久国产婷婷一区二区| 国产香蕉精品视频一区二区三区| 亚洲第一区中文字幕| 超碰日本道色综合久久综合| 日韩电影第一页| 欧美精品videos性欧美| 久久久久久久色| 欧美激情伊人电影| 国模精品系列视频| 青草青草久热精品视频在线网站| 97人人爽人人喊人人模波多| 欧美黑人性视频| 日韩亚洲精品电影| 亚洲一区二区少妇| 色综合天天狠天天透天天伊人| 超碰日本道色综合久久综合| 中文字幕av一区二区三区谷原希美| 在线观看日韩欧美| 欧美日韩在线视频首页| 亚洲久久久久久久久久| 欧美高清无遮挡| 欧美另类高清videos| 精品二区三区线观看| 精品福利一区二区| 久久精品国产91精品亚洲| 亚洲精品一区二区久| 日本中文字幕久久看| 亚洲国产第一页| 中文字幕亚洲综合久久筱田步美| 青青草一区二区| 日韩在线观看精品| 91国产精品视频在线| 久久久久久久久综合| 国产精品久久久久久久久久久久| 国产精品国产三级国产专播精品人| 久久精品国产一区二区电影| 精品亚洲aⅴ在线观看| 欧美激情视频给我| 夜夜嗨av色一区二区不卡| 亚洲色图美腿丝袜| 国产精品久久久久久超碰| 国产一区二区三区高清在线观看| 精品国产一区二区三区久久| 91成品人片a无限观看| 国产免费一区视频观看免费| 国产精品视频公开费视频| 人人做人人澡人人爽欧美| 97欧美精品一区二区三区| 欧美激情乱人伦一区| 91色视频在线导航| 国产精品成人在线| 91精品国产91久久久| 91黑丝高跟在线| 精品夜色国产国偷在线| 亚洲精品视频二区| 欧美剧在线观看| 米奇精品一区二区三区在线观看| 亚洲天堂av在线免费观看| 日韩中文在线观看| 成人午夜在线影院| 久久中文精品视频| 国内精品久久影院| 国产欧美日韩专区发布| 亚洲欧美制服丝袜| 狠狠综合久久av一区二区小说| 免费99精品国产自在在线| 久久精品国产一区二区三区| 久久久久一本一区二区青青蜜月| 欧美日韩成人在线观看| 不卡中文字幕av| 最新91在线视频| 日本乱人伦a精品| 综合久久五月天| 欧美精品videos| 亚洲乱亚洲乱妇无码| 欧美精品精品精品精品免费| 久久精品久久久久电影| 欧美成人免费全部观看天天性色| 在线视频欧美日韩精品| 中国人与牲禽动交精品| 韩国三级电影久久久久久| 91久久久久久国产精品| 欧美成人精品h版在线观看| 精品久久久国产| 亚洲综合色av| 国产精品一区二区电影| 日韩精品视频免费专区在线播放| 亚洲国产精品成人一区二区| 国产精品中文字幕在线观看| 久久久久久久久国产精品| 亚洲人成免费电影| 91精品国产综合久久男男| 亚洲综合av影视| 亚洲直播在线一区| 欧美激情videoshd| 国产主播在线一区| 久久韩国免费视频| 国产一区红桃视频| 久久精品国产电影| 成人福利视频网| 欧美大肥婆大肥bbbbb| 国产视频自拍一区| 亚洲欧美成人一区二区在线电影| 欧美电影在线观看完整版| 国产欧美精品日韩精品| 国产欧美日韩亚洲精品| 国产精品久久久999| 欧美激情图片区| 亚洲精品欧美一区二区三区| 韩日精品中文字幕| 97国产suv精品一区二区62| 亚洲国产免费av| 亚洲精品456在线播放狼人| 日韩电影中文字幕| 国产欧美精品xxxx另类| 精品伊人久久97| 国产亚洲欧美aaaa| 亚洲视频视频在线| 欧美视频一区二区三区…| 日韩中文字幕亚洲|