記錄學習內容。
主要是看網路上的文章和影片,做些紀錄。
大部分內容來自網路上大大的文章
Java Producer Consumer pattern
之前有關執行緒的:
Android ,存圖片到SQLite,process、thread、ByteArrayOutputStream
來了解生產者與消費者:
Java Concurrency Interview: Implement Producer Consumer pattern using wait-notify
producer(生產者):生產食物。
如果 倉庫是滿的 ,就要等待到 顧客發信號(代表:顧客吃了一些東西,所以現在倉庫有空位了),之後繼續生產
Consumer (消费者):吃東西。
如果 倉庫是空的 ,就要等待到 producer(生產者)發出信號(代表: 生產者現在有生產食物了) ,之後繼續吃
把教學影片的程式,照打練習:
第一段用BlockingQueue的方式:
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
public class ThreadTest5 {
static class Ipad {
}
/*static void ConsumerPlayIpad(Ipad ipad) {
System.out.println(" ConsumerPlayIpad: " + ipad.toString() );
}*/
public static void main(String[] args) throws InterruptedException {
BlockingQueue<Ipad> queue = new ArrayBlockingQueue<>(10);
//producer
final Runnable producer = () -> {
while (true) {
try {
Ipad i = new Ipad();
queue.put(i);
System.out.println(" ProducerReleaseIpad ");
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
new Thread(producer).start();
new Thread(producer).start();
//consumer
final Runnable consumer = () -> {
while (true) {
try {
Ipad i = queue.take();
System.out.println(" ConsumerPlayIpad: " + i.toString());
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
new Thread(consumer).start();
new Thread(consumer).start();
}
}
結果:
第二段改成 DIY BlockingQueue :
這邊講到 如果 生產者 只生產 一個東西 ,但是 在等待的消费者有兩個 。
這時候 會不會造成 有一個消費者 吃不到東西 , 所以從if判斷 改成while判斷 ,這樣notEmpty.await();之後 ,就會在跑一次迴圈 ,檢查queue.size() == 0 。
如果用if會發生這個錯誤:
程式:
import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class ThreadTest6 {
static class MyBlockingQueue<E> {
private Queue<E> queue;
private int max = 16;
private ReentrantLock lock = new ReentrantLock(true);
private Condition notEmpty = lock.newCondition();
private Condition notFull = lock.newCondition();
public MyBlockingQueue(int size) {
queue = new LinkedList<>();
this.max = size;
}
public void put(E e) {
lock.lock();
try {
while (queue.size() == max) {
notFull.await();
}
queue.add(e);
Thread.sleep(3000);
System.out.println(" ProducerReleaseIpad ");
notEmpty.signalAll();
} catch (InterruptedException e1) {
e1.printStackTrace();
} finally {
lock.unlock();
}
}
public E take() {
lock.lock();
E item = null;
try {
while (queue.size() == 0) {
notEmpty.await();
}
item = queue.remove();
Thread.sleep(3000);
System.out.println(" ConsumerPlayIpad: " + item.toString());
notFull.signalAll();
} catch (InterruptedException e1) {
e1.printStackTrace();
} finally {
lock.unlock();
}
return item;
}
}
static class Ipad {
}
public static void main(String[] args) throws InterruptedException {
MyBlockingQueue<Ipad> myBlockingQueue = new MyBlockingQueue<Ipad>(5);
//consumer
final Runnable consumer = () -> {
while (true) {
Ipad i = myBlockingQueue.take();
}
};
new Thread(consumer).start();
new Thread(consumer).start();
new Thread(consumer).start();
new Thread(consumer).start();
//producer
final Runnable producer = () -> {
while (true) {
Ipad i = new Ipad();
myBlockingQueue.put(i);
}
};
new Thread(producer).start();
new Thread(producer).start();
}
}
結果:
第三段:
lock 換成 synchronized 。
await() 和signalAll() 換成 wait() 和notifyAll()
目前測試失敗,會有這個錯誤,還不會改:
wait() 和notifyAll()參考:
Day 28 介紹 Producer Consumer 模式