1.生产者消费者wait¬ify版本
代码示例:
/**
* 生产者消费者
* wait¬ify
*/
package com.bernardlowe.concurrent.t04;
import java.util.LinkedList;
import java.util.concurrent.TimeUnit;
public class TestContainer01<E> {
private final LinkedList<E> list = new LinkedList<>(); // LinkedList 模拟生产队列
private final int MAX = 10; // 最大容量
private int count = 0;
public synchronized int getCount(){
return count;
}
// 生产者
public synchronized void put(E e){
while(list.size() == MAX){
try {
this.wait();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
list.add(e);
count++;
this.notifyAll();
}
// 消费者
public synchronized E get(){
E e = null;
while(list.size() == 0){
try{
this.wait();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
e = list.removeFirst();
count--;
this.notifyAll();
return e;
}
public static void main(String[] args) {
final TestContainer01<String> c = new TestContainer01<>();
// 消费者线程进行消费
for(int i = 0; i < 10; i++){
new Thread(new Runnable() {
@Override
public void run() {
for(int j = 0; j < 5; j++){
System.out.println(c.get());
}
}
}, "consumer"+i).start();
}
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 生产者线程进行生产
for(int i = 0; i < 2; i++){
new Thread(new Runnable() {
@Override
public void run() {
for(int j = 0; j < 25; j++){
c.put("container value " + j);
}
}
}, "producer"+i).start();
}
}
}
思考:为什么生产者代码中,为什么要用while判断而不是用if判断?
原因是如果使用if会导致一个虚假唤醒状态,也就是说if只经过一次判断,道道wait()语句的时候可能会休眠,并释放锁,当再次被唤醒的时候,将继续执行wait()之后的语句而不会再去判断是否队列已满,wait/notify和while配合应用,可以避免多线程并发判断逻辑失效问题。
2 生产者消费者Condition版本
Condition版本不使用wait/notify,而是使用ReentrantLock的newCondition()方法得到Condition条件,通过条件判断什么时候加锁或者解锁,如等待唤醒,这样比wait/notify更加直观
/**
* 生产者消费者
* 重入锁&条件
*/
package com.bernardlowe.concurrent.t04;
import java.io.IOException;
import java.util.LinkedList;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class TestContainer02<E> {
private final LinkedList<E> list = new LinkedList<>();
private final int MAX = 10;
private int count = 0;
private Lock lock = new ReentrantLock();
private Condition producer = lock.newCondition();
private Condition consumer = lock.newCondition();
public int getCount(){
return count;
}
public void put(E e){
lock.lock();
try {
while(list.size() == MAX){
System.out.println(Thread.currentThread().getName() + " 等待。。。");
// 进入等待队列。释放锁标记。
// 借助条件,进入的等待队列。
producer.await();
}
System.out.println(Thread.currentThread().getName() + " put 。。。");
list.add(e);
count++;
// 借助条件,唤醒所有的消费者。
consumer.signalAll();
} catch (InterruptedException e1) {
e1.printStackTrace();
} finally {
lock.unlock();
}
}
public E get(){
E e = null;
lock.lock();
try {
while(list.size() == 0){
System.out.println(Thread.currentThread().getName() + " 等待。。。");
// 借助条件,消费者进入等待队列
consumer.await();
}
System.out.println(Thread.currentThread().getName() + " get 。。。");
e = list.removeFirst();
count--;
// 借助条件,唤醒所有的生产者
producer.signalAll();
} catch (InterruptedException e1) {
e1.printStackTrace();
} finally {
lock.unlock();
}
return e;
}
public static void main(String[] args) {
final TestContainer02<String> c = new TestContainer02<>();
for(int i = 0; i < 10; i++){
new Thread(new Runnable() {
@Override
public void run() {
for(int j = 0; j < 5; j++){
System.out.println(c.get());
}
}
}, "consumer"+i).start();
}
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
for(int i = 0; i < 2; i++){
new Thread(new Runnable() {
@Override
public void run() {
for(int j = 0; j < 25; j++){
c.put("container value " + j);
}
}
}, "producer"+i).start();
}
}
}