1、synchronized 实现
public class ProducerConsumerDemo <T>{
LinkedList<T> list = new LinkedList<T>();
final int MAX = 10;
int count = 0;
public synchronized void put(T t){
// 为什么用while而不是if,能否还原错误场景
while(list.size() == MAX){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
list.add(t);
++count;
this.notifyAll();
}
public synchronized T get(){
T t = null;
while(list.size() == 0){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
t = list.removeFirst();
count--;
this.notifyAll();
return t;
}
public static void main(String[] args) {
ProducerConsumerDemo t = new ProducerConsumerDemo();
for (int i = 0; i < 2; i++) {
new Thread(()->{
for (int j = 0; j < 25; j++) {
t.put(Thread.currentThread().getName() + " " + j);
}
},"p" + i).start();
}
for (int i = 0; i < 5; i++) {
new Thread(()->{
for (int j = 0; j < 10; j++) {
System.out.println(t.get());
}
},"c" + i).start();
}
}
}
备注:先跑消费者,当生产者和消费组线程数达到一定数量时,t = list.removeFirst(); 执行报错,
notifyAll() 唤醒的是所有线程,同一个对象同一时刻只能有一个线程拿到锁,若消费者线程拿到锁以后不判断是否有元素,则程序一直往下走,容易报错。
2、Lock 实现
public class LockProducerConsumerDemo<T> {
LinkedList<T> list = new LinkedList<T>();
final int MAX = 10;
int count = 0;
Lock lock = new ReentrantLock();
Condition producer = lock.newCondition();
Condition consumer = lock.newCondition();
public void put(T t){
try{
lock.lock();
while(list.size() == MAX){
producer.await();
}
list.add(t);
++count;
consumer.signalAll();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public T get(){
T t = null;
try{
lock.lock();
while(list.size() == 0){
consumer.await();
}
t = list.removeFirst();
count--;
producer.signalAll();
}catch (Exception e){
}finally {
lock.unlock();
}
return t;
}
public static void main(String[] args) {
LockProducerConsumerDemo t = new LockProducerConsumerDemo();
for (int i = 0; i < 2; i++) {
new Thread(()->{
for (int j = 0; j < 25; j++) {
t.put(Thread.currentThread().getName() + " " + j);
}
},"p" + i).start();
}
for (int i = 0; i < 5; i++) {
new Thread(()->{
for (int j = 0; j < 10; j++) {
System.out.println(t.get());
}
},"c" + i).start();
}
}
}