天天看點

多線程(四) 線程狀态 案例:包子鋪賣包子線程狀态概述睡眠sleep方法等待和喚醒等待喚醒案例(包子鋪賣包子)

線程狀态概述

當線程被建立并啟動以後,它既不是一啟動就進入了執行狀态,也不是一直處于執行狀态。線上程的生命周期中, 有幾種狀态呢?在API中 java.lang.Thread.State 這個枚舉中給出了六種線程狀态: 這裡先列出各個線程狀态發生的條件,下面将會對每種狀态進行詳細解析

多線程(四) 線程狀态 案例:包子鋪賣包子線程狀态概述睡眠sleep方法等待和喚醒等待喚醒案例(包子鋪賣包子)
多線程(四) 線程狀态 案例:包子鋪賣包子線程狀态概述睡眠sleep方法等待和喚醒等待喚醒案例(包子鋪賣包子)

我們不需要去研究這幾種狀态的實作原理,我們隻需知道在做線程操作中存在這樣的狀态。那我們怎麼去了解這幾 個狀态呢,建立與被終止還是很容易了解的,我們就研究一下線程從Runnable(可運作)狀态與非運作狀态之間 的轉換問題。

睡眠sleep方法

我們看到狀态中有一個狀态叫做計時等待,可以通過Thread類的方法來進行示範.

public static void sleep(long time) 讓目前線程進入到睡眠狀态,到毫秒後自動醒來繼續執行

public class Test{
public static void main(String[] args){
for(int i = 1;i<=5;i++){
Thread.sleep(1000);
System.out.println(i)
}
}
}
           

這時我們發現主線程執行到sleep方法會休眠1秒後再繼續執行。

等待和喚醒

Object類的方法 public void wait() : 讓目前線程進入到等待狀态 此方法必須鎖對象調用.

public class Demo2_notify {
public static void main(String[] args) throws InterruptedException {
// 步驟1 : 子線程開啟,進入無限等待狀态, 沒有被喚醒,無法繼續運作.
new Thread(() ‐> {
try {
System.out.println("begin wait ....");
synchronized ("") {
"".wait();
}
System.out.println("over");
} catch (Exception e) {
}
}).start();
//步驟2: 加入如下代碼後, 3秒後,會執行notify方法, 喚醒wait中線程.
Thread.sleep(3000);
new Thread(() ‐> {
try {
synchronized ("") {
System.out.println("喚醒");
"".notify();
}
} catch (Exception e) {
}
}).start();
}
}
           

等待喚醒案例(包子鋪賣包子)

需求分析

定義一個集合,包子鋪線程完成生産包子,包子添加到集合中;吃貨線程完成購買包子,包子從集合中移除。
1. 當包子沒有時(包子狀态為false),吃貨線程等待.
2. 包子鋪線程生産包子(即包子狀态為true),并通知吃貨線程(解除吃貨的等待狀态)
           

代碼示例:

生成包子類:

public class BaoZiPu extends Thread{
private List<String> list ;
public BaoZiPu(String name,ArrayList<String> list){
super(name);
this.list = list;
}
@Override
public void run() {
int i = 0;
while(true){
//list作為鎖對象
synchronized (list){
if(list.size()>0){
//存元素的線程進入到等待狀态
try {
list.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//如果線程沒進入到等待狀态 說明集合中沒有元素
//向集合中添加元素
list.add("包子"+i++);
System.out.println(list);
//集合中已經有元素了 喚醒擷取元素的線程
list.notify();
}
}
}
}
}
           

吃貨包子類:

public class ChiHuo extends Thread {
private List<String> list ;
public ChiHuo(String name,ArrayList<String> list){
super(name);
this.list = list;
}
@Override
public void run() {
//為了能看到效果 寫個死循環
while(true){
//由于使用的同一個集合 list作為鎖對象
synchronized (list){
//如果集合中沒有元素 擷取元素的線程進入到等待狀态
if(list.size()==0){
try {
list.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//如果集合中有元素 則擷取元素的線程擷取元素(删除)
list.remove(0);
//列印集合 集合中沒有元素了
System.out.println(list);
//集合中已經沒有元素 則喚醒添加元素的線程 向集合中添加元素
list.notify();
}
}
}
}
}
           

測試類:

public class Demo {
public static void main(String[] args) {
//等待喚醒案例
List<String> list = new ArrayList<>();
// 建立線程對象
BaoZiPu bzp = new BaoZiPu("包子鋪",list);
ChiHuo ch = new ChiHuo("吃貨",list);
// 開啟線程
bzp.start();
ch.start();
}
}
           

繼續閱讀