生產者和消費者是多線程經典的問題,生產者和消費者問題的核心是同步的問題,同步問題的核心是要保證同一個資源被多個線程並發訪問時的完整性,常用的方法是采用信號或加鎖機制,保證資源在任一時刻只能被一個線程訪問。這一問題用java來實現的話主要有4種方式。1.wait()/notify();2.await()/signal(); 3.blockingQuene 4.PipedInputStream/pipedOutputStream
下面分別來實現。
1.利用wait()和notify()來實現
Wait()方法:當緩沖區已空/滿時,生產者/消費者停止自己的執行,放棄鎖,使自己處於等待狀態,讓其他線程執行。
Notify()方法:當生產者/消費者向緩沖區放入/取出一個產品時,向其他等待的線程發出可執行的通知,同時放棄鎖,使自己處於等待狀態。
Java中介者設計模式 http://www.linuxidc.com/Linux/2014-07/104319.htm
Java 設計模式之模板方法開發中應用 http://www.linuxidc.com/Linux/2014-07/104318.htm
設計模式之 Java 中的單例模式(Singleton) http://www.linuxidc.com/Linux/2014-06/103542.htm
Java對象序列化 http://www.linuxidc.com/Linux/2014-10/107584.htm
大話設計模式(帶目錄完整版) PDF+源代碼 http://www.linuxidc.com/Linux/2014-08/105152.htm
Java中的函數傳遞 http://www.linuxidc.com/Linux/2014-11/109056.htm
下面看看代碼實現:
首先定義商店類:
package ConsumerAndProducerProblem;
import java.util.LinkedList;
/**
* @author: zhuwei
* @ClassName: 商店類
* @Description: TODO
* @Date: 下午3:58:01
*/
public class Storage
{
//定義倉庫最大容量100
private final int MAX_SIZE = 100;
private LinkedList<Object> list= new LinkedList<>();
//生產num個商品
public void produce(int num) throws Exception
{
synchronized(list)
{
//假如倉庫容量不足
if(list.size()+num>MAX_SIZE)
{
System.out.println("倉儲容量不足");
//線程等待
list.wait();
}
//倉庫容量可以容量生產者的生產,則生產
for(int i = 0;i < num;i++)
{
list.add(new Object());
}
System.out.println("生產者生產產品數量為:"+ num);
list.notifyAll();
}
}
//消費num個商品
public void consume(int num) throws Exception
{
synchronized(list)
{
//加入倉庫中的商品不能滿足消費者的需求,線程等待
if(list.size() < num)
{
System.out.println("倉庫中的商品不能滿足消費者需求");
list.wait();
}
for(int i = 0;i < num;i++)
{
list.remove();
}
System.out.println("消費者消費商品數量為:"+num);
list.notifyAll();
}
}
}
定義生產者類
package ConsumerAndProducerProblem;
/**
* @author: zhuwei
* @ClassName: 生產者線程
* @Description: TODO
* @Date: 下午3:57:15
*/
public class Consumer implements Runnable
{
//消費商品數量
private int number;
private Storage storage;
public void consume(int num)
{
try
{
storage.consume(num);
} catch (Exception e)
{
// TODO Auto-generatedcatch block
e.printStackTrace();
}
}
public int getNumber()
{
return number;
}
public void setNumber(int number)
{
this.number = number;
}
public Storage getStorage()
{
return storage;
}
public void setStorage(Storage storage)
{
this.storage = storage;
}
@Override
public void run()
{
// TODO Auto-generatedmethod stub
consume(number);
}
}
定義消費者類:
package ConsumerAndProducerProblem;
/**
* @author: zhuwei
* @ClassName: 消費者線程
* @Description: TODO
* @Date: 下午3:57:38
*/
public class Producer implements Runnable
{
//生產的商品數量
private int number;
private Storage storage;
public void produce(int num)
{
try
{
storage.produce(num);
} catch (Exception e)
{
// TODO Auto-generatedcatch block
e.printStackTrace();
}
}
public int getNumber()
{
return number;
}
public void setNumber(int number)
{
this.number = number;
}
public Storage getStorage()
{
return storage;
}
public void setStorage(Storage storage)
{
this.storage = storage;
}
@Override
public void run()
{
// TODO Auto-generatedmethod stub
produce(number);
}
}
創建測試類:
package ConsumerAndProducerProblem;
public class Test
{
public static void main(String[] args)
{
// TODO Auto-generatedmethod stub
//倉庫對象
Storage storage = new Storage();
//消費者對象
Consumer c1 = new Consumer();
c1.setNumber(10);
c1.setStorage(storage);
Consumer c2 = new Consumer();
c2.setNumber(80);
c2.setStorage(storage);
//生產者對象
Producer p1 = new Producer();
p1.setNumber(20);
p1.setStorage(storage);
Producer p2 = new Producer();
p2.setNumber(50);
p2.setStorage(storage);
p1.run();
c1.run();
p2.run();
c2.run();
}
}
更多詳情見請繼續閱讀下一頁的精彩內容: http://www.linuxidc.com/Linux/2014-11/110031p2.htm