直接上代碼,先看,然後可以想下:Java5.0後引入Concurrent併發包類,採用非阻塞算法來優化實現多線程操作中的併發問題,而之前採用syncronized鎖算法模式。
package com.zbv.producerAndcustomer;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
/**
* 生產者\消費者模式
*/
public class App {
public static Object object = new Object();
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(2);
//Concurrent併發包 LinkedBlockingQueue<E> 就不需要syncronized鎖處理了
// Queue<Integer> queue = new LinkedList<>();
LinkedBlockingQueue<Integer> queue = new LinkedBlockingQueue<>(1);
final Producer producer = new Producer(queue);
Customer customer = new Customer(queue);
executorService.execute(producer);
executorService.execute(customer);
try {
Thread.sleep(10 * 1000);
producer.stop();
customer.stop();
System.out.println("關閉日期=" + timeStr());
executorService.shutdown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static String timeStr() {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
return simpleDateFormat.format(new Date());
}
/**
* 生產者
*/
public static class Producer implements Runnable {
private boolean FLAG = true;
private Queue<Integer> queue;
private int count;
public int getCount() {
return count;
}
public Producer(Queue<Integer> queue) {
this.queue = queue;
}
@Override
public void run() {
while (FLAG) {
count++;
boolean offerResult = false;
try {
synchronized (object) {
offerResult = queue.offer(count);
}
if (offerResult) {
System.out.println("日期:" + timeStr() + " " + Thread.currentThread().getName() + ":生產了第" + count + "產品成功");
} else {
System.out.println("日期:" + timeStr() + " " + Thread.currentThread().getName() + ":生產了第" + count + "產品失敗");
}
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void stop() {
FLAG = false;
}
}
/**
* 消費者
*/
public static class Customer implements Runnable {
private boolean FLAG = true;
private Queue<Integer> queue;
public Customer(Queue<Integer> queue) {
this.queue = queue;
}
@Override
public void run() {
while (FLAG) {
Integer result = null;
try {
synchronized (object) {
result = queue.poll();
}
if (result == null) {
System.out.println("日期:" + timeStr() + " " + Thread.currentThread().getName() + ":當前隊列爲空,無法消費,在等待中...");
} else {
System.out.println("日期:" + timeStr() + " " + Thread.currentThread().getName() + ":消費了第" + result + "產品");
}
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void stop() {
FLAG = false;
}
}
}
使用Object wait notify的生產者消費者模式:
package com.qzx.learningThread.LearningThread;
import java.util.ArrayList;
import java.util.List;
import java.util.PriorityQueue;
import java.util.Queue;
/**
* 使用Object wait notify notifyAll寫一個簡單的消費者、生產者模式
*/
public class ConsumerProducerOne {
private volatile PriorityQueue<String> stringPriorityQueue;
private static final int CapacitySize = 1;
private Object lockObj = new Object();
private volatile boolean needStop = false;
private final Runnable consumer;
private final Runnable producer;
/**
* 結束實驗
*/
public void stopTry() {
needStop = true;
}
public ConsumerProducerOne() {
stringPriorityQueue = new PriorityQueue<>(CapacitySize);
consumer = new ConsumerRunnable();
producer = new ProducerRunnable();
new Thread(consumer).start();
new Thread(producer).start();
}
private class ConsumerRunnable implements Runnable {
@Override
public void run() {
while (!needStop) {
synchronized (lockObj) {
if (stringPriorityQueue.size() <= 0) {
System.out.println("倉庫沒有產品了...");
try {
lockObj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println("consumer happen interrupted exception" + e);
}
}
String obj = stringPriorityQueue.poll();
System.out.println("消費 " + obj);
lockObj.notify();
}
}
}
}
private class ProducerRunnable implements Runnable {
@Override
public void run() {
while (!needStop) {
synchronized (lockObj) {
if (stringPriorityQueue.size() >= CapacitySize) {
System.out.println("倉庫已滿,暫時不需要生產了");
try {
lockObj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println("producer happen interrupted exception" + e);
}
}
//重點:睡眠放在鎖代碼塊外面
// try {
// Thread.sleep(1000);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
System.out.println("生產第" + (stringPriorityQueue.size() + 1) + "個產品");
stringPriorityQueue.offer("這是第" + (stringPriorityQueue.size() + 1) + "個產品");
lockObj.notify();
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
使用Condition的await、signal的生產者消費者模式(這個比object 的wait和notify好用且相對安全)
package com.qzx.learningThread.LearningThread;
import java.util.PriorityQueue;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class ConsumerProducerTwo {
private static final int CapacitySize = 10;
private PriorityQueue<String> stringPriorityQueue = new PriorityQueue<>(CapacitySize);
private final Lock lock = new ReentrantLock();
private Condition consumerCond = lock.newCondition();
private Condition producerCond = lock.newCondition();
private volatile boolean needStop = false;
public void stopTry() {
needStop = true;
}
public ConsumerProducerTwo() {
new Consumer().start();
new Producer().start();
}
private class Consumer extends Thread {
public Consumer() {
}
@Override
public void run() {
super.run();
while (!needStop) {
try {
lock.lock();
if (stringPriorityQueue.size() <= 0) {
try {
consumerCond.await();
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println("consumer happen interrupt exception" + e);
}
}
String obj = stringPriorityQueue.poll();
System.out.println("消費 " + obj);
producerCond.signal();
} finally {
lock.unlock();
}
}
}
}
private class Producer extends Thread {
public Producer() {
}
@Override
public void run() {
super.run();
while (!needStop) {
try {
lock.lock();
if (stringPriorityQueue.size() >= CapacitySize) {
try {
producerCond.await();
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println("producer happen interrupt exception" + e);
}
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("生產第" + (stringPriorityQueue.size() + 1) + "個產品");
stringPriorityQueue.offer("這是第" + (stringPriorityQueue.size() + 1) + "個產品");
consumerCond.signal();
} finally {
lock.unlock();
}
}
}
}
}