線程間通訊------生產者消費者
對於多個生產者和消費者。
為什麼要定義while判斷標記。
原因:讓被喚醒的線程再一次判斷標記。
為什麼定義notifyAll,
因為需要喚醒對方線程。
因為只用notify,容易出現只喚醒本方線程的情況
。導致程式中的所有線程都等待。
class ProducerConsumerDemo
{
public static void main(String[]
args)
{
Resource r=new Resource();
Producer pro=new Producer(r);
Consumer con=new Consumer(r);
Thread t1=new Thread(pro);
Thread t2=new Thread(pro);
Thread t3=new Thread(con);
Thread t4=new Thread(con);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
class Resource
{
private String name;
private int count=1;
private boolean flag=false;
// t1(活著) t2
public synchronized void set(String name)
{
while(flag)
try{wait();}catch(){} //t1(放棄資格)這時候
t2 t3 t4 都有可能搶到運行資格,如果t2搶到
了,true ,t2(放棄資格)
this.name=name+"--"+count++;
Syso(Thread.currentThread().getName()+"....
生產者"+this.name);
flag=true;
this.notifyAll();
}
//t3 t4
public synchronized void out()
{
while(!flay)
try{wait();}catch(){}//t3(放棄資格) t4(放棄
資格)
Syso(Thread.currentThread().getName()+"....
銷售者"+this.name);
flag=false;
this.notifyAll();
}
}
class Producer implements Runnable
{
private Resource res;
Producer(Resource res)
{
this.res=res;
}
public void run()
{
while(true)
{
res.set("XXX");
}
}
}
class Consumer implements Runnable
{
private Resource res;
Consumer(Resource res)
{
this.res=res;
}
public void run()
{
while(true)
{
res.out();
}
}
}
線程間通訊----生產者消費者JDK5.0升級版
JDK5.0的新特性
在Java.Util.Concurrent.locks包裡有一個Lock接
口和Condition介面
JDK1.5中提供了多線程升級解決方案
將同步Synchronized 替換成現實Lock操作。
將Object中的wait,notify,notifyall,替換了
Condition對象。
該對象可以Lock鎖,進行擷取。
在該樣本中,實現了本方只喚醒對方的操作。
import java.util.concurrent.locks.*;
class ProducerConsumerDemo
{
public static void main(String[]
args)
{
Resource r=new Resource();
Producer pro=new Producer(r);
Consumer con=new Consumer(r);
Thread t1=new Thread(pro);
Thread t2=new Thread(pro);
Thread t3=new Thread(con);
Thread t4=new Thread(con);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
class Resource
{
private String name;
private int count=1;
private boolean flag=false;
private Lock lock=new ReentrantLock();
private Condition con_pro=lock.netContion();
private Condition con_con=lock.netContion();
public void set(String name) throws
InterruptedExcetion
{
//先定義一個鎖
lock.lock();
try{
while(flag)
//等待
con_pro.await();
this.name=name+"--"+count++;
Syso(Thread.currentThread().getName()+"....
生產者"+this.name);
flag=true;
//喚醒另一個
con_con.signal();
}falinlly{
//釋放鎖
lock.unlock();
}
}
public void out()
{
lock.lock();
try{
while(!flay)
con_con .await();
Syso(Thread.currentThread().getName()+"....
銷售者"+this.name);
flag=false;
con_pro.signal();
}finally{
lock.unlock();
}
}
}
class Producer implements Runnable
{
private Resource res;
Producer(Resource res)
{
this.res=res;
}
public void run()
{
while(true)
{
try{
res.set("XXX");
}catch(InterruptedException e){
}
}
}
}
class Consumer implements Runnable
{
private Resource res;
Consumer(Resource res)
{
this.res=res;
}
public void run()
{
while(true)
{
while(true)
{
try{
res.out();
}catch(InterruptedException e){
}
}
}
}
停止線程
1、定義迴圈技術標記。
*因為線程運行代碼一般都是迴圈,只要控制了
迴圈即可。
2、使用interrup(中斷)方法、
*該方法是結束線程的凍結狀態,使線程回到運
行狀態中來。
註:stop方法已經過時不再使用。
如何停止線程呢?
只有一種辦法,run方法結束。
開啟多線程運行,運行代碼通常是迴圈結構。
只要控制住迴圈,就可以讓run方法結束,也就是
線程結束。
特殊情況:
當線程處於了凍結狀態。
就不會讀取到標記,那麼線程就不會結束。
當沒有指定的方式讓凍結的線程恢複到運行狀態時
,這時需要對凍結進行清除。
強制讓線程恢複到運行狀態中來。這樣就可以操作
標記讓線程結束。
Thread類提供該方法interrupt();
常用的Thread類中的方法:
1、setDaemon():將該線程標記為守護線程或使用者
線程。
2、join():等待該線程終止。
join的特點:
當A線程執行到了B線程的Join()方法時,A線程就
會等待。等B線程都執行完,A才會執行。
Join可以用來臨時加入線程執行。
3、toString():返回該線程的字串表示形式,
包括線程名稱、優先順序和線程組。
線程組:ThreadGroup類
線程組是個對象。
SetPriority():更改線程的優先順序。
所有的線程預設優先順序為:5
優先順序一共有十級:1到10
1(MIN_PRIORITY)、5(NORM_PRIORITY)、10
(MAX_PRIORITY)跨度最大
yield()方法:暫停當前正在執行的線程對象,並
執行其他線程。