1. 程式人生 > >多執行緒——等待-喚醒機制

多執行緒——等待-喚醒機制

package com.work.wor01;
/**
 * 等待喚醒機制
 * 涉及到了3個方法:
 * 1.wait():等待,將正在執行的執行緒釋放了其執行資格和執行權利,並且將他儲存到執行緒池當中。
 * (執行緒池:運行當中會出現很多正在被凍結的執行緒,都會儲存到執行緒持當中,執行緒池其實就是容器,用來儲存執行緒物件的,
 * 暫時不用的執行緒也要留著)
 * 
 * 2.notify():喚醒,喚醒了執行緒池中被wait的(等待的)執行緒,注意一次只能喚醒一個,而且喚醒的執行緒物件是任意的。
 * 
 * 3.notifyAll():喚醒全部,將執行緒池中所有被wait的執行緒都喚醒了。
 * 
 * 喚醒就是讓執行緒池中的執行緒具備了執行資格。
 * 這些方法只有使用在同步中才有效。
 * 這些方法在使用時必須要表明所屬的鎖,這樣我們才能明確方法操作的到底上哪個鎖上的執行緒。
 * 
 * 為什麼操作這些執行緒的方法定義在了Object當中?
 * 這些方法在使用是必須要表明所屬的鎖,而鎖可以是任意物件,能被任意物件呼叫的方法一定定義在Object類當中。
 * 
 * wait notify方法api的描述當中提到了物件監聽器,指的就是鎖。
 * */

//資源類
class Resource{
	String name;
	String sex;
	//設定一個標誌位,用來區分輸入/輸出操作
	boolean flag;
}
//描述輸入任務的類
class input implements Runnable{
	Resource r;
	//任務一旦初始化就將資源傳進來,任務一產生必須有資源
	public input(Resource r) {
		super();
		this.r = r;
	}

	@Override
	public void run() {
		int x = 0;
		while(true){
			synchronized (r) {
				//判斷標誌位,如果有資料就說還沒輸出,當前執行緒等待,如果沒有資料就執行當前執行緒
				if(r.flag){
					try {
						Thread.sleep(10);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
				if(x==0){
					r.name = "小紅";
					r.sex = "女";
				}else{
					r.name = "小軍";
					r.sex = "男";
				}
				r.flag = true;
				r.notify();
				x=(x+1)%2;//判斷x是否等於0
			}
		}
	}
}
//描述輸出任務的類
class output implements Runnable{
	Resource s;

	public output(Resource s) {
		super();
		this.s = s;
	}

	@Override
	public void run() {
		while(true){
			synchronized (s) {
				if(!s.flag){
					try {
						Thread.sleep(10);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
				System.out.println(s.name+"....."+s.sex);
				s.flag = false;
				s.notify();
			}
		}
	}
}
public class Resourcework01 {
	public static void main(String[] args) {
		//建立資源物件
		Resource r = new Resource();
		//建立執行緒任務物件
		input in = new input(r);
		output out = new output(r);
		//建立執行緒物件
		Thread t1 = new Thread(in);
		Thread t2 = new Thread(out);
		//開啟執行緒
		t1.start();
		t2.start();
	}
}