生产者消费者问题(JAVA实现)
版本一:
package cn.edu.nankai.producterandconsumer;
import java.util.LinkedList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import javax.swing.JOptionPane;
public class ConsumerAndProducer {
private static int numberOfProducer;
private static int numberOfConsumer;
private static int eachWorksOfProducer;
private static int eachWorksOfConsumer;
private static int sizeOfBuffer = 2;
private static Buffer buffer = new Buffer();
public static void main(String[] args){
numberOfProducer = Integer.parseInt(JOptionPane.showInputDialog("请输入你想要的生产者数量"));
numberOfConsumer = Integer.parseInt(JOptionPane.showInputDialog("请输入你想要的消费者数量"));
eachWorksOfProducer = Integer.parseInt(JOptionPane.showInputDialog("请输入你想要每个生产者生产的数量"));
eachWorksOfConsumer = Integer.parseInt(JOptionPane.showInputDialog("请输入你想要每个消费者消费的数量"));
sizeOfBuffer = Integer.parseInt(JOptionPane.showInputDialog("请输入缓冲区大小"));
JOptionPane.showMessageDialog(null, "生产者数量是 " + numberOfProducer +"\n消费者数量是 " + numberOfConsumer+
"\n每个生产者生产的数量是 " + eachWorksOfProducer + "\n每个消费者消费的数量是 " + eachWorksOfConsumer +
"\n缓冲区大小是 " + sizeOfBuffer);
ExecutorService executor = Executors.newFixedThreadPool(numberOfConsumer + numberOfProducer);
for(int i = 0;i < numberOfProducer;i++)
executor.execute(new ProducerTask(i));
for(int i = 0;i < numberOfConsumer;i++)
executor.execute(new ConsumerTask(i));
executor.shutdown();
while(!executor.isTerminated());
JOptionPane.showMessageDialog(null, "线程全部运行完毕\n");
}
private static class ProducerTask implements Runnable{
int id;
public ProducerTask(int id) {
super();
this.id = id;
}
@Override
public void run() {
// TODO Auto-generated method stub
int i = 1;
try{
for(int j = 0;j < eachWorksOfProducer;j++){
System.out.println("Producer" + id + " writes " + i);
buffer.write(i++);
Thread.sleep((int)(Math.random()*1000));
}
}catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
private static class ConsumerTask implements Runnable{
int id;
public ConsumerTask(int id) {
super();
this.id = id;
}
@Override
public void run() {
// TODO Auto-generated method stub
try {
for(int i = 0;i < eachWorksOfConsumer;i++){
System.out.println("Consumer" + id + " reads " + buffer.read());
Thread.sleep((int)(Math.random()*2000));}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
版本二:
package cn.edu.nankai.pac;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.LinkedList;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Buffer {
final String pro = "生产者";
final String con = "消费者";
private LinkedList queue = new LinkedList();
private Lock lock = new ReentrantLock();
private int indexOfBuffer = 0;
private Condition notEmpty = lock.newCondition();
private Condition notFull = lock.newCondition();
private int size;
private int id;
Buffer(int id,int size){
this.id = id;
this.size = size;
}
public LinkedList getList(){
return queue;
}
public void write(int value,int time,int pid,long tid){
try {
Thread.sleep(time = Information.randomTime(2,4));
} catch (InterruptedException e) {
// TODO Auto-generated catch block
//e.printStackTrace();
Information.output("生产者 " + pid +"(线程号" + tid+ ")运行完毕");
}
Information.output("生产者 " + pid +"(线程号" + tid + ")生产用时" + time + "姓名:" + Information.NAME + " 学号:" + Information.ID);
Information.output(pro + pid + "(线程号" + tid + ")试图进入缓冲区" + id);
lock.lock();
Information.output(pro + pid + "(线程号:" + tid + ")进入了第" + id + "个缓冲区,");
try {
while(queue.size() == size){
Information.output("缓冲区" + id + "已满,"+ pro + pid + "(线程号:" + tid+ ")正在等待");
notFull.await();
}
queue.offer(value);
Information.which.offer(id);
indexOfBuffer++;
Information.output(pro + pid + "(线程号:" + tid + ")在第" + id +"个缓冲区生产了一个产品" + value + "缓冲区序号" + indexOfBuffer);
notEmpty.signalAll();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
lock.unlock();
Information.output(pro + pid + "(线程号:" + tid+ ")离开缓冲区" + id + "\n");
}
}
@SuppressWarnings("finally")
public int read(int time,int cid,long tid){
int value = 0;
Information.output(con + cid + "(线程号:" + tid + ")试图进入缓冲区" + id);
lock.lock();
Information.output(con + cid + "(线程号:" + tid + ")进入了第" + id + "个缓冲区");
try {
while(queue.size() == 0){
Information.output("缓冲区" + id + "已空,"+ con + cid + "(线程号:" + tid+ ")正在等待");
notEmpty.await();
}
value = queue.remove();
indexOfBuffer--;
Information.output(con + cid + "(线程号:" + tid + ")再第" + id + "个缓冲区消费了一个产品" + value + "缓冲区序号:" + indexOfBuffer);
notFull.signalAll();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
lock.unlock();
Information.output(con + cid + "(线程号:" + tid + ")离开缓冲区" + id + "\n");
try {
Thread.sleep(time = Information.randomTime(2,4));
} catch (InterruptedException e) {
// TODO Auto-generated catch block
//e.printStackTrace();
Information.output("消费者 " + cid +"(线程号" + tid + ")运行完毕");
}
Information.output("从缓冲区" + id + " 的消费者 " + cid +"(线程号" + tid + ")消费用时" + time + "姓名:" + Information.NAME + " 学号:" + Information.ID);
return value;
}
}
}
package cn.edu.nankai.pac;
public class Consumer extends Thread{
int cid;
int i = 0;
volatile static Integer count = 0;
Consumer(int cid){
this.cid = cid;
}
@Override
public void run() {
// TODO Auto-generated method stub
while(count <= 8){
synchronized (count){
if(count == 8){
Information.output("消费者" + cid + "已停止运行");
break;
}
int time = 0;
if(Information.which.size() != 0){
switch(Information.which.remove()){
case 1:
synchronized (count) {
if(count < 8){
count++;
}else{
break;
}
}
Main.firstBuffer.read(time, cid,this.getId());
break;
case 2:
synchronized (count) {
if(count < 8){
count++;
}else{
break;
}
}
Main.secondBuffer.read(time, cid,this.getId());
break;
default:
System.err.println("缓冲区选择错误");
break;
}
}else{
Information.output("所有缓冲区都是空的");
}
synchronized (count){
if(count == 8){
Information.output("消费者" + cid + "已停止运行");
break;
}
}
}
}
}
}
package cn.edu.nankai.pac;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.LinkedList;
public class Information {
final static String NAME="王文涵";
final static String ID="1212603";
//static String s = "";
public volatile static LinkedList which = new LinkedList();
public static int whichBuffer(){
return (int)(Math.random() * 100) % 2 == 0 ? 1 : 2;
}
public static int randomTime(int start,int end){
return (int)(Math.random()*1000*(end - start)) + start*1000;
}
public static void output(String s){
System.out.println(s);
try {
BufferedWriter writer = new BufferedWriter(new FileWriter(new File("d:\\Result.txt"), true));
writer.append(s + "\n\n\n");
writer.flush();
writer.close();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} // true代表追加
}
}
package cn.edu.nankai.pac;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javax.swing.JOptionPane;
public class Main {
public final static int numberOfProducer = 3;
public final static int numberOfConsumer = 2;
static Buffer firstBuffer = new Buffer(1,1);
static Buffer secondBuffer = new Buffer(2,2);
public volatile static Integer sum = 0;
public static void main(String[] args){
final ExecutorService executor = Executors.newFixedThreadPool(numberOfConsumer + numberOfProducer);
for(int i = 0;i < numberOfProducer;i++)
executor.execute(new Producter(i));
for(int i = 0;i < numberOfConsumer;i++)
executor.execute(new Consumer(i));
executor.shutdown();
while(!executor.isTerminated() && !(Consumer.count == 8 && Producter.count == 8)){
// System.out.println("Consumer is " + Consumer.count + ",Producter is " + Producter.count);
// try {
// Thread.sleep(1000);
// } catch (InterruptedException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
}
executor.shutdownNow();
JOptionPane.showMessageDialog(null, "线程全部运行完毕\n");
System.out.println("all is over");
}
}
package cn.edu.nankai.pac;
public class Producter extends Thread{
int pid;
int i = 0;
volatile static Integer count = 0;
Producter(int pid){
this.pid = pid;
}
@Override
public void run() {
// TODO Auto-generated method stub
while(count <= 8){
synchronized (count){
if(count == 8){
Information.output("消费者" + pid + "已停止运行");
break;
}
int time = 0;
switch(Information.whichBuffer()){
case 1:
synchronized (count) {
if(count < 8){
count++;
}else{
break;
}
}
Main.firstBuffer.write(i++, time, pid,this.getId());
break;
case 2:
synchronized (count) {
if(count < 8){
count++;
}else{
break;
}
}
Main.secondBuffer.write(i++, time, pid,this.getId());
break;
default:
Information.output("缓冲区选择错误");
break;
}
synchronized (count){
if(count == 8){
Information.output("生产者" + pid + "停止运行");
break;
}
}
}
}
}
}
版本三:(南开软件学院东哥操作系统典型题,无私分享给学妹们了)
package cn.edu.nankai.pac;
import java.util.LinkedList;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import static cn.edu.nankai.pac.Information.*;
public class Buffer {
private LinkedList queue = new LinkedList();
private Lock lock = new ReentrantLock();
private Condition notEmpty = lock.newCondition();
private Condition notFull = lock.newCondition();
private int id;
private int size;
private int indexOfBuffer = 0;
Buffer(int id,int size){
this.id = id;
this.size = size;
}
synchronized public int getListSize(){
return queue.size();
}
public void write(int value,int pid,long tid,int type){
String str = type == P ? pro : mov;
output(str + pid + " 线程号:" + tid + "姓名:" + NAME + " 学号:" + ID);
output(str + pid + " 线程号:" + tid + "试图进入缓冲区" + id);
lock.lock();
output(str + pid + " 线程号:" + tid + "进入了第" + id + "个缓冲区,");
try {
while(queue.size() == size){
Information.output("缓冲区" + id + "已满,"+ str + pid + " 线程号:" + tid+ "正在等待");
notFull.await();
}
queue.offer(value);
which.offer(id);
indexOfBuffer++;
output(str + pid + " 线程号:" + tid + "在第" + id +"个缓冲区放入了一个产品" + value + "缓冲区序号" + indexOfBuffer);
notEmpty.signalAll();
} catch (InterruptedException e) {
e.printStackTrace();
}finally{
lock.unlock();
output(str + pid + "线程号:" + tid+ "离开了缓冲区" + id + "\n");
}
}
public int read(int cid,long tid,int type){
int value = 0;
String str = type == C ? con : mov;
output(str + cid + " 线程号:" + tid + "试图进入缓冲区" + id);
lock.lock();
output(str + cid + " 线程号:" + tid + "进入了第" + id + "个缓冲区");
try {
while(queue.size() == 0){
output("缓冲区" + id + "已空,"+ str + cid + " 线程号:" + tid+ "正在等待");
notEmpty.await();
}
value = queue.remove();
indexOfBuffer--;
output(str + cid + " 线程号:" + tid + "在第" + id + "个缓冲区取出了一个产品" + value + "缓冲区序号:" + indexOfBuffer);
notFull.signalAll();
} catch (InterruptedException e) {
e.printStackTrace();
}finally{
lock.unlock();
output(str + cid + "(线程号:" + tid + ")离开缓冲区" + id + "\n");
}
return value;
}
}
package cn.edu.nankai.pac;
import static cn.edu.nankai.pac.Information.*;
public class Consumer extends Thread{
private int cid;
private static Integer ccount = 0;
public Consumer(int cid) {
//super();
this.cid = cid;
}
@Override
public void run() {
//super.run();
while(true){
System.out.println(con + ":" + ccount);
synchronized (ccount) {
if(ccount < totelProduct){
ccount++;
buffer[2].read(cid, this.getId(), C);
}else{
break;
}
}
long time;
try {
Thread.sleep(time = Information.randomTime(2,4));
output(con + cid + " 线程号:" + this.getId() + " 消费产品总共用时:" + ((double)time)/1000 + "秒");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(con + cid + " 线程号:" + this.getId() + "已经停止运行");
}
public void setCid(int cid) {
this.cid = cid;
}
public int getCid() {
return cid;
}
}
package cn.edu.nankai.pac;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.LinkedList;
import javax.swing.JOptionPane;
public class Information {
//各种常量字符串和类型
public final static String NAME="王文涵";
public final static String ID="1212603";
public final static String pro = "生产者";
public final static String con = "消费者";
public final static String mov = "移动者";
public final static int P = 0;
public final static int C = 1;
public final static int M = 2;
//题目相关的变量
public static int numberOfProducter = 3;
public static int numberOfConsumer = 3;
public static int numberOfMover = 2;
public static int numberOfBuffer = 3;
public static int totelProduct = 3;
public static int []eachBufferSize = new int[numberOfBuffer];
public volatile static LinkedList which = new LinkedList();
public static Buffer [] buffer = new Buffer[numberOfBuffer];
public static int ERR = 1000;
private static void initBufferSize(){
for(int i = 0;i < numberOfBuffer;i++)
eachBufferSize[i] = 2;
}
public static void initBuffer(){
initBufferSize();
for(int i = 0;i < numberOfBuffer;i++)
buffer[i] = new Buffer(i,eachBufferSize[i]);
}
public static void handleInput(){
numberOfProducter = Integer.parseInt(JOptionPane.showInputDialog("请输入第一个人的数量"));
numberOfConsumer = Integer.parseInt(JOptionPane.showInputDialog("请输入第二个人的数量"));
numberOfMover = Integer.parseInt(JOptionPane.showInputDialog("请输入第三个人的数量"));
numberOfBuffer = Integer.parseInt(JOptionPane.showInputDialog("请输入缓冲区的数量"));
totelProduct = Integer.parseInt(JOptionPane.showInputDialog("总共要生产的产品的数量"));
eachBufferSize = new int[numberOfBuffer];
for(int i = 0;i < numberOfBuffer;i++)
eachBufferSize[i] = Integer.parseInt(JOptionPane.showInputDialog("请输入第" + (i+1) + "个缓冲区的大小"));
}
public static int whichBuffer(){
return (int)(Math.random() * 100) % 2 == 0 ? 1 : 2;
}
public static int randomTime(int start,int end){
return (int)(Math.random()*1000*(end - start)) + start*1000;
}
public static void output(String s){
System.out.println(s);
try {
BufferedWriter writer = new BufferedWriter(new FileWriter(new File("d:\\Result.txt"), true));// true代表追加
writer.append(s + "\n\n\n");
writer.flush();
writer.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
package cn.edu.nankai.pac;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javax.swing.JOptionPane;
import static cn.edu.nankai.pac.Information.*;
public class Main {
public static void main(String[] args){
initBuffer();
final ExecutorService executor = Executors.newFixedThreadPool(numberOfConsumer + numberOfProducter + numberOfMover);
for(int i = 0;i < numberOfProducter;i++)
executor.execute(new Producter(i));
for(int i = 0;i < numberOfMover;i++){
Mover m = new Mover(i);
m.setBuffer(buffer[i], buffer[i+1]);
executor.execute(m);
}
for(int i = 0;i < numberOfConsumer;i++)
executor.execute(new Consumer(i));
executor.shutdown();
while(!executor.isTerminated()){
}
executor.shutdownNow();
JOptionPane.showMessageDialog(null, "线程全部运行完毕\n");
System.out.println("all is over");
}
}
package cn.edu.nankai.pac;
import static cn.edu.nankai.pac.Information.output;
import static cn.edu.nankai.pac.Information.*;
public class Mover extends Thread{
private int mid;
private Integer mcount = 0;
private Buffer start = new Buffer(ERR, 0);
private Buffer end = new Buffer(ERR,0);
public Mover(int mid) {
//super();
this.mid = mid;
}
public void setBuffer(Buffer start,Buffer end){
this.start = start;
this.end = end;
}
@Override
public void run() {
//super.run();
while(true){
System.out.println(mov + mid +":" + mcount);
//synchronized (mcount) {
if(mcount < totelProduct){
mcount++;
int value = this.start.read(mid, this.getId(), M);
long time;
try {
Thread.sleep(time = Information.randomTime(2,4));
output(mov + mid + " 线程号:" + this.getId() + " 移动产品总共用时:" + ((double)time)/1000 + "秒");
} catch (InterruptedException e) {
e.printStackTrace();
output(mov + mid + " 线程号:" + this.getId() + "运行完毕");
}
this.end.write(value, mid, this.getId(), M);
}else{
break;
}
//}
}
System.out.println(mov + mid + " 线程号:" + this.getId() + "已停止运行");
}
public void setMid(int mid) {
this.mid = mid;
}
public int getMid() {
return mid;
}
}
package cn.edu.nankai.pac;
import static cn.edu.nankai.pac.Information.*;
public class Producter extends Thread{
private int pid;
private static Integer pcount = 0;
public Producter(int pid) {
//super();
this.pid = pid;
}
@Override
public void run() {
//super.run();
while(true){
System.out.println(pro + ":" + pcount);
long time;
try {
Thread.sleep(time = Information.randomTime(2,4));
output(pro + pid + " 线程号:" + this.getId() + " 生产产品总共用时:" + ((double)time)/1000 + "秒");
} catch (InterruptedException e) {
e.printStackTrace();
output(pro + pid + " 线程号:" + this.getId() + "运行完毕");
}
//System.out.println("Reach there0");
synchronized (pcount) {
//System.out.println("Reach there1");
if(pcount < totelProduct){
pcount++;
//System.out.println(pro + pid + " 线程号:" + this.getId() + "加一");
buffer[0].write(0, pid, this.getId() , P);
}else{
System.out.println(pro + pid + " 线程号:" + this.getId() + "已经停止运行");
break;
}
}
}
}
public void setPid(int pid) {
this.pid = pid;
}
public int getPid() {
return pid;
}
}