線程間的通行與等待喚醒機制舉例:
一、兩個線程:
/**
* @author flame
* @createDate 2012-1-3
* 線程間的通信:
* 首先,有一個資源,提供存取對象
* 一個線程往裡面注入資源
* 另一個線程從裡面讀取資源
* 多個線程操作同一個個資料,不同的是操作動作不同
* 喚醒機制:
* 為避免一個資源注入一般就被另一個資源所讀取,是以需要采用喚醒機制。
* 原理:注入時,注入線程執行狀态,讀取線程等待狀态;注入後,注入線程等待狀态,讀取線程執行狀态。
* wait()等待
* notify()喚醒單一線程
* notifyAll()喚醒所有線程
* 喚醒隻能喚醒同一個鎖的等待線程,不能喚醒不同鎖的等待線程,也就是說等待線程的鎖和喚醒線程的鎖必須同一個。
*/
/**
* 資源,提供姓名和性别
* @author flame
* @createDate 2012-1-3
*/
class Result
{
private String name;
private String sex;
private boolean flag = false;
public synchronized void set(String name, String sex)
{
if(flag)
try{this.wait();}catch(InterruptedException ex){}
this.name = name;
this.sex = sex;
flag = true;
this.notify();
}
public synchronized void get()
{
if(!flag)
try{this.wait();}catch(InterruptedException ex){}
System.out.println(this.name+"...."+this.sex);
this.flag = false;
this.notify();
}
}
/**
* 注入資源線程
* @author flame
* @createDate 2012-1-3
*/
class InputInfo implements Runnable
{
private Result r; //聲明資源類
public InputInfo(Result r) //傳入一個資源類,以是得資源為同個資源
{
this.r = r;
}
public void run()
{
int i= 0,j =0;
while(i <=500)
{
if(j == 0)
r.set("flame", "man");
else
r.set("火", "男");
j = (j+1)%2;
i++;
}
}
}
/**
* 擷取資源中的資料
* @author flame
* @createDate 2012-1-3
*/
class OutputInfo implements Runnable
{
private Result r;
public OutputInfo(Result r)
{
this.r = r;
}
public void run()
{
int i = 0;
while(i<500)
{
r.get();
i++;
}
}
}
public class communcationThreadDemo {
/**
* 啟動線程
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Result r = new Result();
new Thread(new InputInfo(r)).start();
new Thread(new OutputInfo(r)).start();
}
}
二、多線程 (生産者與消費者)
/**
* 生産者與消費者舉例
* 當出現多個線程時,喚醒機制的另一種解決方式
* @author flame
* @createDate 2012-1-3
*/
/**
* 資源類
* 初始化資源對象
* 控制資源注入和輸出線程
* @author flame
* @createDate 2012-1-3
*/
class Ruselt
{
private String name;
private int count =0;
private boolean flag = false;
public synchronized void set(String name)
{
while(flag)
try{
this.wait();
}catch(InterruptedException ex)
{
System.out.println(ex.getMessage());
}
this.name = name +"***----***"+count++;
System.out.println(Thread.currentThread().getName()+"******生産者******"+this.name);
this.flag = true;
this.notifyAll();
}
public synchronized void get()
{
while(!flag) //此處如果采用if語句判斷,會使得當以線程判斷通過而放棄資格後,在蘇醒時會不再經過判斷而繼續執行下面的代碼
try{
this.wait();
}catch(InterruptedException ex)
{
System.out.println(ex.getMessage());
}
System.out.println(Thread.currentThread().getName()+"=====消費者================="+name);
this.flag = false;
this.notifyAll(); //喚醒所有線程,避免全部線程處于等待狀态
}
}
class InputComm implements Runnable
{
private Ruselt r;
public InputComm(Ruselt r)
{
this.r = r;
}
public void run()
{
int i=0;
while(i<500)
{
r.set("商品");
i++;
}
}
}
class OutputComm implements Runnable
{
private Ruselt r;
public OutputComm(Ruselt r)
{
this.r = r;
}
public void run()
{
int i=0;
while(i<500)
{
r.get();
i++;
}
}
}
public class moreThreadDemo {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Ruselt r = new Ruselt();
new Thread(new InputComm(r)).start();
new Thread(new OutputComm(r)).start();
}
}