麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 學院 > 開發(fā)設計 > 正文

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

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

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

線程的生命周期

1、線程的生命周期

線程從產生到消亡的過程

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

線程生命周期狀態(tài)圖

誕生狀態(tài)

線程剛剛被創(chuàng)建

就緒狀態(tài)

線程的 start 方法已被執(zhí)行

線程已準備好運行

運行狀態(tài)

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

阻塞狀態(tài)(Blocked)

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

遇到用synchronized標記的方法而未獲得其監(jiān)視器暫時不能進入執(zhí)行時

休眠狀態(tài)(Sleeping)

執(zhí)行sleep方法而進入休眠

死亡狀態(tài)

線程已完成或退出

2、死鎖問題

死鎖

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

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

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

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

創(chuàng)建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();    //創(chuàng)建一個球類對象        Player0 p0 = new Player0(ball);    //創(chuàng)建0號游戲者        Player1 p1 = new Player1(ball);    //創(chuàng)建1號游戲者        Player2 p2 = new Player2(ball);    //創(chuàng)建2號游戲者        p0.start();    //啟動0號游戲者        p1.start();    //啟動1號游戲者        p2.start();    //啟動2號游戲者    }}

運行結果:

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

程序說明:

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

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

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

3、控制線程的生命

結束線程的生命

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

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

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

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

class TestThread1 extends Thread {    private boolean flag = true;    public void stopme() {    //在此方法中控制循環(huán)條件        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線程    }}

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

線程的優(yōu)先級

線程調度

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

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

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

線程的優(yōu)先級

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

在線程A運行過程中創(chuàng)建的新的線程對象B,初始狀態(tài)具有和線程A相同的優(yōu)先級

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

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

基于線程優(yōu)先級的線程調度

具有較高優(yōu)先級的線程比優(yōu)先級較低的線程優(yōu)先執(zhí)行

對具有相同優(yōu)先級的線程,Java的處理是隨機的

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

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

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

一個具有更高優(yōu)先級的線程變?yōu)榫途w狀態(tài)(Ready);

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

對于支持時間分片的系統(tǒng),時間片的時間期滿

例子:創(chuàng)建兩個具有不同優(yōu)先級的線程,都從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();    //放棄執(zhí)行權            }        }    }}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

結果說明:

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

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

如果在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();    //放棄執(zhí)行權                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

說明

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

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

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

您還可能感興趣:

java學習筆記系列:

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

java學習筆記13--反射機制與動態(tài)代理

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--開發(fā)環(huán)境平臺總結


發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 久久久一区二区三区精品 | 羞羞网站| 姑娘第四集免费看视频 | 羞羞羞羞视频 | 国产99视频精品免视看9 | 亚州综合一区 | 一级黄色毛片播放 | 日日做夜夜操 | 国产99久久久国产精品 | 国产色爱综合网 | 亚洲成人免费网站 | 在线视频观看国产 | 亚洲成人网一区 | av电影在线免费观看 | 九九视屏 | 欧日韩在线 | av在线日韩 | 欧美中文在线 | 亚洲第一视频 | 久草在线小说 | 国产永久免费观看 | 中国av免费在线观看 | 中国女人内谢8xxxxxx在 | 日韩av日韩 | 欧美 日韩 中文 | 欧美14一15sex性hd | 精品影视一区二区 | 国产美女视频一区 | 日韩黄在线 | 国产91九色 | 国产三级三级三级三级 | 久色精品| 有兽焉免费动画 | 在线a| 色综合视频 | 午夜精品福利视频 | 欧美黄色一级片在线观看 | 亚洲第一成人久久网站 | 宅男噜噜噜66国产在线观看 | 日韩一级电影在线观看 | 久久综合久久综合久久 |