生产者消费者模式
1,生产者只在仓库未满时进行生产,仓库满时生产者进程被阻塞。
2,消费之只在仓库非空时进行消费,仓库为空时消费者进程被阻塞。
生产者消费者问题都是通过锁的竞争进行资源的消耗或生产。
方法一:synchronized,wait,notify
资源
public class Resource {
//当前资源的数量
int number = 0;
//当前资源的上限
int size = 10;
//控制执行的标识
boolean flag = true;
//生产资源
public synchronized void produce() {
//如果资源满了,就进入阻塞状态
//jdk里推荐用while,因为有可能出现虚假唤醒,所以再次确认
while (number == size) {
try {
System.out.println(Thread.currentThread().getName() + "\t" + "进入等待");
//线程进入阻塞状态,并释放锁
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
number++;
System.out.println(Thread.currentThread().getName() + "\t" + "生产资源" + number);
//唤醒其他正在等待的线程
this.notify();
}
//消费资源
public synchronized void consume() {
//如果num为0,没有资源了,需要等待
//这里jdk源码里推荐用while,因为有可能虚假唤醒,所以要再次确认
while (number == 0) {
try {
System.out.println(Thread.currentThread().getName() + "\t" + "进入等待");
//线程等待,并释放锁
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + "\t" + "消费资源" + number);
number--;
//唤醒其他正在等待的线程
this.notify();
}
//停止执行
public void stop() {
this.flag = false;
}
}
生产者
public class Producer implements Runnable {
private Resource resource;
public Producer(Resource resource){
this.resource=resource;
}
@Override
public void run() {
while (resource.flag){
resource.produce();
}
System.out.println(Thread.currentThread().getName()+"\t"+"生产者停止线程");
}
}
消费者
public class Consumer implements Runnable {
private Resource resource;
public Consumer(Resource resource){
this.resource=resource;
}
@Override
public void run() {
while (resource.flag){
resource.consume();
}
System.out.println(Thread.currentThread().getName()+"\t"+"消费者停止线程");
}
}
测试代码
public class TestProducerAndConsumer {
public static void main(String[] args) {
Resource resource = new Resource();
Thread producer=new Thread(new Producer(resource),"producer");
Thread consumer=new Thread(new Consumer(resource),"consumer");
producer.start();
consumer.start();
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("停止线程");
resource.flag=false;
}
}
方法二:lock,condition,await,singal
资源
public class Resource {
//当前资源的数量
int number = 0;
//当前资源的上限
int size = 10;
//控制执行的标识
boolean flag = true;
//创建所对象
Lock lock = new ReentrantLock();
//创建锁的条件、情况
Condition condition = lock.newCondition();
//生产资源
public void produce() {
//开启锁
lock.lock();
try {
//当资源满时,需要等待
//jdk源码里推荐使用while,因为有可能出现虚假唤醒,所以再次确认
while (number == size) {
System.out.println(Thread.currentThread().getName() + "\t" + "进入等待");
try {
//线程等待,释放锁
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
number++;
System.out.println(Thread.currentThread().getName() + "\t" + "生产资源" + number);
//唤醒其他线程
condition.signal();
} finally {
lock.unlock();
}
}
//消费资源
public void consume() {
//开启锁
lock.lock();
try {
//如果number为0,没有资源了,需要等待
//jdk源码里推荐使用while,因为有可能出现虚假唤醒,所以再次确认
while (number == 0) {
System.out.println(Thread.currentThread().getName() + "\t" + "进入等待");
try {
//线程等待,释放锁
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + "\t" + "消费资源" + number);
number--;
//唤醒其他线程
condition.signal();
} finally {
//释放锁
lock.unlock();
}
}
public void stop() {
this.flag = false;
}
}
生产者、消费者和测试代码都和上面一样。
方法三:BlockingQueue
资源
public class Resource {
AtomicInteger atomicInteger=new AtomicInteger();
boolean flag=true;
BlockingQueue blockingQueue=null;
public Resource(BlockingQueue blockingQueue){
this.blockingQueue=blockingQueue;
}
public void produce(){
try {
int number = atomicInteger.incrementAndGet();
boolean result = blockingQueue.offer(number, 2L, TimeUnit.SECONDS);
if(result){
System.out.println(Thread.currentThread().getName()+"\t"+"生产资源成功"+number);
}else{
System.out.println(Thread.currentThread().getName()+"\t"+"生产资源失败"+number);
}
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void consume(){
try {
Integer number =(Integer) blockingQueue.poll(2L, TimeUnit.SECONDS);
if(number==null){
flag=false;
System.out.println(Thread.currentThread().getName()+"\t"+"超过2秒钟消费资源,线程停止");
return;
}
System.out.println(Thread.currentThread().getName()+"\t"+"消费资源"+number);
//atomicInteger.getAndDecrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void stop(){
this.flag=false;
}
}
生产者
public class Producer implements Runnable {
Resource resource=null;
public Producer(Resource resource){
this.resource=resource;
}
@Override
public void run() {
while (resource.flag){
resource.produce();
}
System.out.println(Thread.currentThread().getName()+"\t"+"生产线程停止了");
}
}
消费者
public class Consumer implements Runnable {
Resource resource=null;
public Consumer(Resource resource){
this.resource=resource;
}
@Override
public void run() {
while (resource.flag){
resource.consume();
}
System.out.println(Thread.currentThread().getName()+"\t"+"消费线程停止了");
}
}
测试代码
public class TestProducerAndConsumer {
public static void main(String[] args) {
BlockingQueue<Integer> blockingQueue=new ArrayBlockingQueue<>(10);
Resource resource=new Resource(blockingQueue);
Thread producer = new Thread(new Producer(resource), "producer");
Thread consumer = new Thread(new Consumer(resource), "consumer");
producer.start();
consumer.start();
try {
TimeUnit.SECONDS.sleep(30);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("停止线程");
resource.flag=false;
}
}