wait与notify、notifyAll:
-- 属于Object类的方法,一个对象只能提供一个同步控制
-- 与synchronize搭配使用
wait与signal、signalAll:
-- 属于Condition类的方法,一个锁可以提供多个Condition同步控制
-- 与Lock.lock()、unlock()搭配使用
以生产者消费者为例,说明两者的使用情景
/**
* 生产者父类
*/
public abstract class AbstractProducer implements Runnable{
protected int a = 0;
protected Queue<String> queue;
protected String name;
protected abstract void create();
public AbstractProducer(Queue<String> queue, String name){
this.queue = queue;
this.name = name;
}
protected boolean isFull(Queue<?> queue){
return queue.size() >= 10;
}
@Override
public void run() {
// 默认生产100次
while(true){
create();
try {
if(a<20)
Thread.sleep(10);
else
Thread.sleep(40);
if(a>100) {
System.out.println("Producer break");
break;
}
} catch (InterruptedException e) {
}
}
}
}
/**
* 消费者父类
*/
public abstract class AbstractConsumer implements Runnable{
protected Queue<String> queue;
protected String name;
public AbstractConsumer(Queue<String> queue, String name){
this.queue = queue;
this.name = name;
}
protected abstract void handle();
@Override
public void run() {
while(true){
handle();
try {
Thread.sleep(20);
} catch (InterruptedException e) {
}
}
}
}
wait--notifyAll 实现方式
同步过程:创建一个队列,当队列为空,消费者进入等待状态;当队列满了,生产者进入等待状态。
当消息队列为空,消费者进入等待,释放锁;然后生产者获取到锁,队列没满,所以生产者生产一个消息,并唤醒所有等待线程,消费者被唤醒,此时消费者还不能运行,需要等生产者退出代码同步块后,消费者才真的开始运行。
/**
* 生产者
*/
public class ProducerWaitNotify extends AbstractProducer {
ProducerWaitNotify(Queue<String> queue, String name){
super(queue, name);
}
@Override
protected void create(){
a++;
String str = a+"";
synchronized (queue){
while(isFull(queue)){
System.out.println("queue is full,"+name+" wait");
try{
queue.wait();
}catch(Exception e){}
}
queue.add(str);
System.out.println(name+" create "+str);
queue.notifyAll();
}
}
}
/**
* 消费者
*/
public class ConsumerWaitNotify extends AbstractConsumer {
public ConsumerWaitNotify(Queue<String> queue, String name){
super(queue, name);
}
public void handle(){
String str = null;
synchronized (queue){
while(queue.isEmpty()){
System.out.println("queue is empty,"+name+" wait.");
try{
queue.wait();
}catch(Exception e){}
}
str = queue.poll();
System.out.println(name+" handle "+str);
queue.notifyAll();
}
}
}
public class Main {
public static void main(String[] args) {
//创建两个消费者,两个生产者
Queue<String> queue = new ArrayDeque<>();
Thread producer1 = new Thread(new ProducerWaitNotify(queue,"p1"));
Thread producer2 = new Thread(new ProducerWaitNotify(queue,"p2"));
Thread consumer1 = new Thread(new ConsumerWaitNotify(queue,"c1"));
Thread consumer2 = new Thread(new ConsumerWaitNotify(queue,"c2"));
producer1.start();
producer2.start();
consumer1.start();
consumer2.start();
}
}
wait--signal方式实现
同步过程:先创建一个锁对象,然后再创建两个条件,条件1是队列不为空,条件2是队列不满。
当队列为空时,消费者在条件1上进行等待;当队列满了时,生产者在条件2上等待。因为条件1和条件2不会同时满足,所以消费者和生产者不会同时进入等待。
消费者消费一个消息后,就唤醒条件2;生产者生产一个消息后,就唤醒条件1
/**
* 同步信号
*/
public class LockSignal {
private static Lock lock = new ReentrantLock();
private static Condition noFullCondition = lock.newCondition();
private static Condition noEmptyCondition = lock.newCondition();
public static Lock getLock(){
return lock;
}
public static Condition getNoFullCondition(){
return noFullCondition;
}
public static Condition getNoEmptyCondition(){
return noEmptyCondition;
}
}
/**
* 消费者
*/
public class ConsumerWaitSignal extends AbstractConsumer {
ConsumerWaitSignal(Queue<String> queue, String name){
super(queue, name);
}
protected void handle(){
String str;
LockSignal.getLock().lock();
try {
while (queue.isEmpty()) {
System.out.println("queue is empty," + name + " wait.");
try {
LockSignal.getNoEmptyCondition().await();
} catch (Exception e) {
LockSignal.getNoEmptyCondition().signal();
}
}
str = queue.poll();
System.out.println(name + " handle " + str);
LockSignal.getNoFullCondition().signal(); //只唤醒生产者
}finally {
LockSignal.getLock().unlock();
}
}
}
/**
* 生产者
*/
public class ProducerWaitSignal extends AbstractProducer {
ProducerWaitSignal(Queue<String> queue, String name){
super(queue,name);
}
@Override
protected void create(){
a++;
String str = a+"";
LockSignal.getLock().lock();
try {
while (isFull(queue)) {
System.out.println("queue is full," + name + " wait");
try {
LockSignal.getNoFullCondition().await();
} catch (Exception e) {
LockSignal.getNoFullCondition().signal();
}
}
queue.add(str);
System.out.println(name + " create " + str);
LockSignal.getNoEmptyCondition().signal();//只唤醒消费者
}finally {
LockSignal.getLock().unlock();
}
}
}
public class Main {
public static void main(String[] args) {
Queue<String> queue = new ArrayDeque<>();
//创建两个生产者,两个消费者
Thread producer1 = new Thread(new ProducerWaitSignal(queue,"p1"));
Thread producer2 = new Thread(new ProducerWaitSignal(queue,"p2"));
Thread consumer1 = new Thread(new ConsumerWaitSignal(queue,"c1"));
Thread consumer2 = new Thread(new ConsumerWaitSignal(queue,"c2"));
consumer1.start();
consumer2.start();
producer1.start();
producer2.start();
}
}
以上内容如果不足欢迎指出