消费者与生产者模式
一. 使用synchronized,队列,wait,notify
加锁保证同一时刻只有一个线程对缓存进行读或写操作,当队列满了的时候,wait等待,生产完后就通知消费者可以消费了
上代码
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
public class ProducerAndConsumer {
private final int MAX_LEN = 3;
private Queue<Integer> queue = new LinkedList<Integer>();
class Producer extends Thread {
@Override
public void run() {
producer();
}
private void producer() {
synchronized (queue) {
while (queue.size() == MAX_LEN) {
queue.notify();
System.out.println("当前队列满");
try {
queue.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
queue.add(1);
queue.notify();
System.out.println("生产者生产一条任务,当前队列长度为" + queue.size());
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Consumer extends Thread {
@Override
public void run() {
consumer();
}
private void consumer() {
//将queue上锁,防止多线程
synchronized (queue) {
while (queue.size() == 0) {
queue.notify();
System.out.println("当前队列为空");
try {
queue.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
queue.poll();
queue.notify();
System.out.println("消费者消费一条任务,当前队列长度为" + queue.size());
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
ProducerAndConsumer pc = new ProducerAndConsumer();
List<Producer> pList=new ArrayList();
List<Consumer> cList=new ArrayList();
for (int i = 0; i <50 ; i++) {
pList.add(pc.new Producer());
cList.add(pc.new Consumer());
}
for (int i = 0; i <50 ; i++) {
pList.get(i).start();
cList.get(i).start();
}
}
}
二. lock版
Lock锁属于轻量锁,推荐使用,使用时还能设置等待时间,灵活地实现多路通知
package com.hc.springcloud.custom;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class ProducerAndConsumerLock {
private final static int MAX_LEN = 10;
private static Queue<Integer> queue = new LinkedList<Integer>();
private final static Lock lock = new ReentrantLock();
private final static Condition condition = lock.newCondition();
class Producer extends Thread {
@Override
public void run() {
producer();
}
private void producer() {
lock.lock();
try {
while (queue.size() == MAX_LEN) {
System.out.println("当前队列满");
try {
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
queue.add(1);
condition.signal();
System.out.println("生产者生产一条任务,当前队列长度为" + queue.size());
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
} finally {
lock.unlock();
}
}
}
class Consumer extends Thread {
@Override
public void run() {
consumer();
}
private void consumer() {
lock.lock();
try {
while (queue.size() == 0) {
System.out.println("当前队列为空");
try {
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
queue.poll();
condition.signal();
System.out.println("消费者消费一条任务,当前队列长度为" + queue.size());
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
} finally {
lock.unlock();
}
}
}
public static void main(String[] args) {
ProducerAndConsumerLock test = new ProducerAndConsumerLock();
new Thread(test.new Producer()).start();
new Thread(test.new Consumer()).start();
new Thread(test.new Producer()).start();
new Thread(test.new Consumer()).start();
new Thread(test.new Producer()).start();
new Thread(test.new Consumer()).start();
new Thread(test.new Producer()).start();
new Thread(test.new Consumer()).start();
}
}
三.基于信号量
package com.hc.springcloud.custom;
import java.util.concurrent.Semaphore;
public class ProducerAndConsumerSemaphore {
private static Integer count = 0;
//创建三个信号量
//这个是生产者许可,最多可以获取10个许可,十个生产者。
final Semaphore provider = new Semaphore(10);
//这个是消费者许可。
final Semaphore consumer = new Semaphore(0);
//体现互斥的地方:保证生产者和消费者之间的交替进行 所以再设置一个mutex信号量(互斥量)
final Semaphore mutex = new Semaphore(1);
public static void main(String[] args) {
ProducerAndConsumerSemaphore test = new ProducerAndConsumerSemaphore();
new Thread(test.new Producer()).start();
new Thread(test.new Consumer()).start();
new Thread(test.new Producer()).start();
new Thread(test.new Consumer()).start();
new Thread(test.new Producer()).start();
new Thread(test.new Consumer()).start();
new Thread(test.new Producer()).start();
new Thread(test.new Consumer()).start();
}
//acquire()方法尝试获得一个准入的许可。若无法获得,则线程会等待,直到有线程释放一个许可或当前线程被中断.
//release()方法用于在线程访问资源结束后,释放一个许可。以使其他等待许可的线程可以进行资源访问.
class Producer implements Runnable {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
provider.acquire();//生产者先行,获得许可,因为final Semaphore provider = new Semaphore(10);
mutex.acquire();
count++;// 生产一个
System.out.println(Thread.currentThread().getName()
+ "生产者生产,目前总共有" + count);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
mutex.release();
// acquire与release之间的关系:
consumer.release();//生产完产品,消费者获取到了许可。
}
}
}
}
class Consumer implements Runnable {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(3000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
try {
consumer.acquire();
mutex.acquire();
count--;
System.out.println(Thread.currentThread().getName()
+ "消费者消费,目前总共有" + count);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
mutex.release();
provider.release();
}
}
}
}
}