一、生产者消费者问题描述:
有一群生产者进程在生产产品,并将这些产品提供给消费者进程去消费。为使生产者进程与消费者进程能并发执行,在两者之间设置了一个具有n个缓冲区的缓冲池,生产者进程将其所生产的产品放入一个缓冲区中;消费者进程可从一个缓冲区取走产品去消费。
二、程序分析
生产者进程和消费者进程需要实现同步和线程通信:
生产者生产产品,放入缓冲池中,消费者从缓冲池中取走产品,生产者和消费者互相独立;
缓冲池满时,生产者不能生产产品;缓冲池空时,消费者不能消费产品;
三、代码分析:
需要4个类,队列(queue)、生产者、消费者、Main()
队列:用字符串数组模拟缓冲池,队列需要入队、出队、判断是否为空、是否为满;
入队、出队实现同步;
设置两个指针,分别指示空和满;
四、同步锁 Lock:
Lock lock=new ReentratLock();
* lock.lock();//上锁
* lock.unlock();//解锁
Condition c=lock.newCondition();
* c.await();主动等待
* c.signal();唤醒其他一个
* c.signalAll();唤醒所有
五、代码:
队列:
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class queue {
private String[] data=new String[10];
private int front=0,tail=0;//front:头,消费时-1,tail:尾,生产时+1
Lock lk=new ReentrantLock();
Condition notEmpty=lk.newCondition();//满
Condition notFull=lk.newCondition();//空
public boolean enQueue(String s) throws InterruptedException{//入队
lk.lock();
if(isFull()){
System.out.println("queue is full");
notFull.await();
}
data[tail]=s;
tail=(tail+1)%data.length;
notEmpty.signal();
lk.unlock();//唤醒出队
return true;
}
public String outQueue() throws InterruptedException{//出队
lk.lock();
if(isEmpty()){
System.out.println("queue is empty");
notEmpty.await();
}
String s=data[front];
front=(front+1)%data.length;
notFull.signal();//唤醒入队
lk.unlock();
return s;
}
public boolean isEmpty(){
return front==tail;
}
public boolean isFull(){
return (tail+1)%data.length==front;
}
}
Producer:
public class Productr implements Runnable{
private queue q;
private int pid;
Productr(queue q,int pid){
this.q=q;
this.pid=pid;
}
@Override
public void run() {
int tid=0;
int id=0;
while(true){
try {
Thread.sleep(1000);
id=pid*100+tid;//id=生产者编号*1000+线程编号
q.enQueue(id+"");
System.out.println("producer "+"created "+id);
tid++;
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
break;
}
}
}
}
消费者:
public class Consumer implements Runnable{
private queue q;
private int cid;
Consumer(queue q,int cid){
this.q=q;
this.cid=cid;
}
public void run() {
while(true){
int t=(int)(Math.random()*1000);
try {
Thread.sleep(t);
String s=q.outQueue();
System.out.println("Consumer "+cid+" eat "+s);
} catch (InterruptedException e) {
e.printStackTrace();
break;
}
}
}
}
Main:
public class Main {
public static void main(String[] args) {
queue queue=new queue();
for(int i=0;i<10;i++){
Productr p=new Productr(queue,i);
Thread t=new Thread(p);
t.start();
}
for(int i=0;i<10;i++){
Consumer c=new Consumer(queue,i);
Thread t=new Thread(c);
t.start();
}
}
}