1 wait()和notify实现生产消费者模型
package com.qunar.conditionTest;
import java.util.PriorityQueue;
/**
* Created by chen on 2018/4/22.
*/
public class Testwaitnotify {
private int queueSize = 10;
private PriorityQueue<Integer> queue = new PriorityQueue<>(queueSize);
public static void main(String[] args) {
Testwaitnotify test = new Testwaitnotify();
Producer producer = test.new Producer();
Consumer consumer = test.new Consumer();
producer.start();
consumer.start();
}
class Consumer extends Thread {
public void run(){
consume();
}
private void consume(){
while (true) {
synchronized (queue) { //进入同步代码块
while (queue.size() == 0) {//这里一定要使用while不能使用if,因为当生产者生产一个商品时,会调用notifyAll唤醒所有consumer等待线程,while保证只有一个线程能过通过,其他consumer 线程在while条件中再次被wait
try {
queue.wait(); //让当前线程等待,必须在同步代码块中执行
} catch (InterruptedException e) {
e.printStackTrace();
queue.notify(); //异常是唤醒当前等待线程
}
}
queue.poll();
queue.notify(); //释放当前线程持有的对象锁
System.out.println("从队列中取走一个元素,队列剩余"+queue.size()+"个元素");
}
}
}
}
class Producer extends Thread {
public void run(){
prooduce();
}
private void prooduce() {
while (true){
synchronized(queue){
while (queue.size() == queueSize){ //这里也一样,必须使用while做判断语句,保证每次允许一个线程通过,其他线程在while循环中再次被wait
try {
queue.wait();
} catch (InterruptedException e) {
e.printStackTrace();
queue.notify();
}
}
queue.add(1);
queue.notify();
System.out.println("向队列取中插入一个元素,队列剩余空间:"+(queueSize-queue.size()));
}
}
}
}
}
2 使用ReetrantLock方式实现生产消费模型
package com.qunar.conditionTest;
import java.util.PriorityQueue;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* Created by jw.chen on 2018/4/22.
*/
public class TestReentrantLock {
private int queueSize = 1;
private PriorityQueue<Integer> queue = new PriorityQueue<>(queueSize);
private Lock lock = new ReentrantLock(); //定义ReetrantLock锁
private Condition produceLock = lock.newCondition(); //produce条件锁
private Condition consumeLock = lock.newCondition(); //consume条件锁
public static void main(String[] args) {
TestReentrantLock test = new TestReentrantLock();
Producer producer = test.new Producer();
Consumer consumer = test.new Consumer();
producer.start();
consumer.start();
}
class Consumer extends Thread {
public void run(){
consume();
}
private void consume(){
while (true) {
lock.lock(); //condition条件锁必须在同步代码块中执行
try {
while (queue.size() == 0) {
System.out.println("队列空,等待数据");
try {
consumeLock.await(); //队列为空时,让consume锁等待,注意这里使用的是await()不是wait()方法,
} catch (InterruptedException e) {
e.printStackTrace();
}
}
queue.poll();
produceLock.signal(); //消费后释放produce lock,使其继续生产工作
System.out.println("从队列取走一个元素,队列剩余" + queue.size() + "个元素");
}finally {
lock.unlock(); //finally中释放锁
}
}
}
}
class Producer extends Thread {
public void run(){
prooduce();
}
private void prooduce() {
while (true){
lock.lock();
try {
while (queue.size() == queueSize) {
try {
produceLock.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
queue.offer(1);
System.out.println("向队列取中插入一个元素,队列剩余空间:"+(queueSize-queue.size()));
consumeLock.signal();
} finally {
lock.unlock();
}
}
}
}
}
需要注意的点
使用条件锁,需要在Lock环境下使用,condition锁使用的wait方法是await方法,这里需要注意
使用condition.signal()唤醒对应条件的应用