生产者消费者问题(java多线程)
实验内容
(1)设置存放产品的缓冲区的个数为6个。
(2)信号量机制实现生产者和消费者对缓冲区的互斥访问。
(3)生产者生产产品时,要输出当前缓冲区冲产品的个数和存放产品的位置。
(4)消费者消费产品时,要输出当前缓冲区冲产品的个数和消费产品的位置。
(5)用多线程的并发实现生产者进程和消费者进程的同步。
实验原理
为了使生产者进程和消费之进程能并发执行,在两者之间设置了一个具有n个缓冲区的缓冲池,生产者进程将其所生产的产品放入一个缓冲区中;消费者进程可以从一个缓冲区中取走产品去消费。
假定在生产者和消费者之间的公用缓冲池具有n个缓冲区,这是可以利用互斥信号量mutex实现诸进程对缓冲池的互斥使用;利用信号量notfull和notempty分别表示缓冲池中满缓冲区和空缓冲区的数量。同时假定这些生产者和消费者相互等效,只要缓冲池未满,生产者便可将消息送入缓冲池;只要缓冲池未空,消费之便可以从缓冲池取走一个消息。
Semaphore是一个计数信号量,它的本质是一个"共享锁"。信号量维护了一个信号量许可集。线程可以通过调用acquire()来获取信号量的许可;当信号量中有可用的许可时,线程能获取该许可;否则线程必须等待,直到有可用的许可为止。 线程可以通过release()来释放它所持有的信号量许可。
我们也可以创建计数为1的Semaphore,将其作为一种类似互斥锁的机制,这也叫二元信号量,表示两种互斥状态。计数为0的Semaphore是可以release的,然后就可以acquire(即一开始使线程阻塞从而完成其他执行。)。
代码
class Producer implements Runnable {
Clerk clerk = new Clerk();
public Producer(Clerk clerk){
this.clerk = clerk;
}
@Override
public void run() {
try {
clerk.getNotFull().acquire();
clerk.getMutex().acquire();
clerk.getList().add(new Object());
System.out.println("【生产者" + Thread.currentThread().getName() +
"】生产一个产品,产品存放位置为:" + clerk.getList().size() +
",现库存:" + clerk.getList().size());
} catch (Exception e) {
e.printStackTrace();
} finally {
clerk.getMutex().release();
clerk.getNotEmpty().release();
}
}
}
class Consumer implements Runnable {
Clerk clerk = new Clerk();
public Consumer(Clerk clerk){
this.clerk = clerk;
}
@Override
public void run() {
try {
clerk.getNotEmpty().acquire();
clerk.getMutex().acquire();
clerk.getList().remove();
System.out.println("【消费者" + Thread.currentThread().getName() +
"】消费一个产品,消费产品位置为:" + (clerk.getList().size() + 1) +
",现库存:" + clerk.getList().size());
} catch (Exception e) {
e.printStackTrace();
} finally {
clerk.getMutex().release();
clerk.getNotFull().release();
}
}
}
import java.util.LinkedList;
import java.util.concurrent.Semaphore;
public class Clerk {
private LinkedList<Object> list = new LinkedList<Object>();
// 仓库的最大容量
Semaphore notFull = new Semaphore(6);
public void setNotFull(Semaphore notFull) {
this.notFull = notFull;
}
public void setNotEmpty(Semaphore notEmpty) {
this.notEmpty = notEmpty;
}
public void setMutex(Semaphore mutex) {
this.mutex = mutex;
}
public LinkedList<Object> getList() {
return list;
}
public void setList(LinkedList<Object> list) {
this.list = list;
}
public Semaphore getNotFull() {
return notFull;
}
public Semaphore getNotEmpty() {
return notEmpty;
}
public Semaphore getMutex() {
return mutex;
}
// 将线程挂起,等待其他来触发
Semaphore notEmpty = new Semaphore(0);
// 互斥锁
Semaphore mutex = new Semaphore(1);
}
public class Demo_ProducerComsumer {
public static void main(String[] args) {
Clerk clerk = new Clerk();
int t = 12;
while(t-- != 0){
new Thread(new Producer(clerk)).start();
new Thread(new Consumer(clerk)).start();
}
}
}
运行结果
多线程并发执行12次之后的结果,在此也可以让它while里面的参数变量为true,一直执行,方便更好的观察并发执行和互斥访问

浙公网安备 33010602011771号