Java 面試大全〖九〗生產者消費者模式
生產者消費者模式是通過一個容器來解決生產者和消費者的強耦合問題。生產者和消費者彼此之間不直接通訊,而通過阻塞隊列來進行通訊,所以生產者生產完數據之後不用等待消費者處理,直接扔給阻塞隊列,消費者不找生產者要數據,而是直接從阻塞隊列裏取,阻塞隊列就相當於一個緩衝區,平衡了生產者和消費者的處理能力。這個阻塞隊列就是用來給生產者和消費者解耦的。
一. synchronized實現
加粗樣式
package JUC.ComuserAndProducer;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class CandP1 {
private int num = 0;
public synchronized void increament() throws InterruptedException {
while (num != 0) {
this.wait();
}
num++;
System.out.println(Thread.currentThread().getName() + " 線程生產了,還剩下: " + num);
this.notifyAll();
}
public synchronized void decreament() throws InterruptedException {
while (num == 0) {
this.wait();
}
num--;
System.out.println(Thread.currentThread().getName() + " 線程消費了,還剩下: " + num);
this.notifyAll();
}
}
public class ComsumerAndProducerSync {
public static void main(String[] args) {
CandP1 candP1=new CandP1();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
candP1.increament();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"A").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
candP1.decreament();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"B").start();
}
}
二. Lock實現
package JUC.ComuserAndProducer;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class CandP{
private int num=0;
Lock lock=new ReentrantLock();
Condition condition=lock.newCondition();
public void increament() throws InterruptedException {
lock.lock();
try{
while(num!=0){
condition.await();
}
num++;
System.out.println(Thread.currentThread().getName()+" 線程生產了,還剩下: "+num);
condition.signalAll();
}finally {
lock.unlock();
}
}
public void decreament() throws InterruptedException {
lock.lock();
try{
while(num==0){
condition.await();
}
num--;
System.out.println(Thread.currentThread().getName()+" 線程消費了,還剩下: "+num);
condition.signalAll();
}finally {
lock.unlock();
}
}
}
public class ComsumerAndProducer {
public static void main(String[] args) {
CandP candP=new CandP();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
candP.increament();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"A").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
candP.decreament();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"B").start();
}
}
三. 阻塞隊列實現
package JUC.ComuserAndProducer;
import java.sql.Time;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
class MyResource{
private volatile boolean Flag=true; //默認開啓進行生產消費
private AtomicInteger atomicInteger=new AtomicInteger(); //原子整形
BlockingQueue blockingQueue=null;//我們傳接口,不傳具體實現類,具體實現類由我們自己決定,口子放的足夠寬
public MyResource(BlockingQueue blockingQueue) {
this.blockingQueue = blockingQueue;
System.out.println(blockingQueue.getClass().getName()); //檢查進來的是什麼對象
}
public void MyProducer1() throws InterruptedException {
String data=null;
while(Flag){
data = atomicInteger.getAndIncrement()+"";
boolean offer = blockingQueue.offer(data, 2L, TimeUnit.SECONDS);
if(offer){
System.out.println(Thread.currentThread().getName()+"\t"+data+"插入成功");
}else {
System.out.println(Thread.currentThread().getName()+"\t"+data+"插入失敗");
}
TimeUnit.SECONDS.sleep(1);
}
System.out.println(Thread.currentThread().getName()+"\t"+"生產停止");
}
public void MyConsumer1() throws InterruptedException {
String data=null;
while(Flag){
data = (String) blockingQueue.poll(2L,TimeUnit.SECONDS);
if(data==null||data.equalsIgnoreCase("")){
Flag=false;
System.out.println(Thread.currentThread().getName()+"\t"+data+" 2s沒取到消費失敗");
System.out.println();
return;
}
System.out.println(Thread.currentThread().getName()+"\t"+data+"消費成功");
}
}
public void StopAll(){
Flag=false;
}
}
public class ComsumerAndProducerBlockingQueue {
public static void main(String[] args) throws InterruptedException {
MyResource myResource=new MyResource(new SynchronousQueue());
ExecutorService executorService=Executors.newCachedThreadPool();
Thread thread = new Thread(() -> {
try {
myResource.MyProducer1();
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "生產者A1");
executorService.execute(thread);
new Thread(()->{
try {
myResource.MyConsumer1();
} catch (InterruptedException e) {
e.printStackTrace();
}
},"消費者B1").start();
TimeUnit.SECONDS.sleep(6);
myResource.StopAll();
executorService.shutdown();
}
}