Semaphore实现生产者与消费者问题,通俗易懂
一、分析
生产者与消费者中需要关注的核心问题有两个:
- 生产者不能同时放
- 消费者不能同时消费
对象抽象
消费者、生产者、仓库
二、源码:
仓库
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Semaphore;
/**
* @author VernHe
*/
public class Buffer {
//同时进入核心区的人数
Semaphore mutex = new Semaphore(1);
//空位的数量
Semaphore notFull = new Semaphore(5);
//产品的数量
Semaphore notEmpty = new Semaphore(0);
//操作的仓库
private List<String> list = new ArrayList<>(5);
/**
* 放入产品
* @param str
* @throws InterruptedException
*/
public void write(String str) throws InterruptedException {
//仓库有空位时
notFull.acquire();
try {
//看有没有线程在核心区
mutex.acquire();
//放入产品
list.add(str);
} finally {
//退出核心区
mutex.release();
//增加一个不空的位置
notEmpty.release();
}
}
/**
* 取出产品
* @return
* @throws InterruptedException
*/
public String read() throws InterruptedException{
//有产品可以拿的时候
notEmpty.acquire();
try {
//进入核心区
mutex.acquire();
//拿产品
return list.remove(0);
} finally {
//退出核心区
mutex.release();
//空位增加
notFull.release();
}
}
}
生产者
/**
* 生产者,放入产品
* @author VernHe
*/
public class Producer implements Runnable{
private Buffer buffer;
public Producer(Buffer buffer) {
this.buffer = buffer;
}
public Buffer getBuffer() {
return buffer;
}
public void setBuffer(Buffer buffer) {
this.buffer = buffer;
}
public Producer() {
}
@Override
public void run() {
String char1="hello";
for (int i = 0; i < 5; i++) {
String str = String.valueOf(char1.charAt(i));
try {
buffer.write(str);
System.out.println(Thread.currentThread().getName() + "写入 <--- " + str);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
消费者
/**
* 消费者,消费产品
* @author VernHe
*/
public class Consumer implements Runnable{
private Buffer buffer;
public Consumer() {
}
public Consumer(Buffer buffer) {
this.buffer = buffer;
}
public Buffer getBuffer() {
return buffer;
}
public void setBuffer(Buffer buffer) {
this.buffer = buffer;
}
@Override
public void run() {
String c;
StringBuffer result = new StringBuffer();
for (int i = 0; i < 5; i++) {
// for (int i = 0; i < 5; i++) {
try {
c = buffer.read();
result.append(c);
System.out.println(Thread.currentThread().getName() + "读到 ---> " + c);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.printf("最终读取的结果为:" + result.toString());
}
}
测试
/**
* @author VernHe
*/
public class Pv {
public static void main(String[] args) {
Buffer buffer = new Buffer();
Producer producer = new Producer(buffer);
Consumer consumer = new Consumer(buffer);
/**
* 一个生产者一个消费者
*/
Consumer consumer2 = new Consumer(buffer);
Thread t1 = new Thread(producer,"Producer_01");
Thread t2 = new Thread(consumer,"Consumer_01");
t1.start();
t2.start();
}
}
对于实现多个生产者多个消费者,只需要多定义几个生产者消费者对象即可