其实这个类我也忘记的差不多了, 但是经常看看的别人来说这个类,但是我是真的已经忘记了, 所以今天也来学习一下
Condition介绍
Condition是在java 1.5中才出现的,它用来替代传统的Object的wait()、notify()实现线程间的协作,相比使用Object的wait()、notify(),使用Condition的await()、signal()这种方式实现线程间协作更加安全和高效。因此通常来说比较推荐使用Condition,阻塞队列实际上是使用了Condition来模拟线程间协作。
Condition是个接口,基本方法就是await() 和 signal()方法, signalAll()
Condition依赖于Lock接口,生成一个Condition的基本代码是lock.newCondition()
调用Condition的await()和signal()方法,都必须在lock保护之内,就是说必须在lock.lock()和lock.unlock之间才可以使用
Conditon中的await()对应Object的wait();
Condition中的signal()对应Object的notify();
Condition中的signalAll()对应Object的notifyAll()。
使用上面的区别(其实也是需要获取到lock的锁才行)
public class TestCondition {
final Lock lock = new ReentrantLock();
final Condition condition = lock.newCondition();
public static void main(String[] args) {
// TODO Auto-generated method stub
TestCondition test = new TestCondition();
Producer producer = test.new Producer();
Consumer consumer = test.new Consumer();
consumer.start();
producer.start();
}
class Consumer extends Thread{
@Override
public void run() {
consume();
}
private void consume() {
try {
lock.lock();
System.out.println("我在等一个新信号"+this.currentThread().getName());
condition.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally{
System.out.println("拿到一个信号"+this.currentThread().getName());
lock.unlock();
}
}
}
class Producer extends Thread{
@Override
public void run() {
produce();
}
private void produce() {
try {
lock.lock();
System.out.println("我拿到锁"+this.currentThread().getName());
condition.signalAll();
System.out.println("我发出了一个信号:"+this.currentThread().getName());
} finally{
lock.unlock();
}
}
}
}
Condition的执行方式,是当在线程Consumer中调用await方法后,线程Consumer将释放锁,并且将自己沉睡,等待唤醒,线程Producer获取到锁后,开始做事,完毕后,调用Condition的signalall方法,唤醒线程Consumer,线程Consumer恢复执行。
以上说明Condition是一个多线程间协调通信的工具类,使得某个,或者某些线程一起等待某个条件(Condition),只有当该条件具备( signal 或者 signalAll方法被带调用)时 ,这些等待线程才会被唤醒,从而重新争夺锁(只有获取到锁才能从await的地方继续执行)。
基于这个的阻塞队列
package com.xiaomi.browser.filter;
import java.util.PriorityQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* ClassName: BlockQueue
* Package: com.xiaomi.browser.filter
* Description:
* Datetime: 2021/4/24 下午4:00
* Author: liuwei
*/
public class BlockQueue {
static PriorityQueue<Integer> queue = new PriorityQueue<>(5);
static Lock lock = new ReentrantLock();
static Condition produceCon = lock.newCondition();
static Condition consumeCon = lock.newCondition();
public static void main(String[] args) {
Producer producer = new Producer();
Consumer consumer = new Consumer();
producer.start();
consumer.start();
}
static class Consumer extends Thread {
volatile boolean flag = true;
@Override
public void run() {
while (true) {
lock.lock();
try {
if (queue.isEmpty()) {
System.out.println(" 队列为空等待数据");
consumeCon.await();
}
Integer poll = queue.poll();
System.out.println("从队列中取走一个元素"+ poll + "队列中剩余的元素大小为" + queue.size() + "个元素");
// 唤醒元素
TimeUnit.MICROSECONDS.sleep(200);
produceCon.signalAll();
} catch (Exception e) {
System.out.println("抛出元素");
} finally {
// 释放元素
lock.unlock();
}
}
}
}
static class Producer extends Thread {
volatile boolean flag = true;
@Override
public void run() {
while (true) {
lock.lock();
try {
if (queue.size() == 5) {
System.out.println(" 队列已满");
produceCon.await();
}
queue.add(1);
System.out.println("从队列中塞一个元素队列中剩余的元素大小为" + queue.size() + "个元素");
// 唤醒元素
consumeCon.signalAll();
} catch (Exception e) {
System.out.println("抛出元素");
} finally {
// 释放元素
lock.unlock();
}
}
}
}
}
Condition接口
condition可以通俗的理解为条件队列。当一个线程在调用了await方法以后,直到线程等待的某个条件为真的时候才会被唤醒。这种方式为线程提供了更加简单的等待/通知模式。Condition必须要配合锁一起使用,因为对共享状态变量的访问发生在多线程环境下。一个Condition的实例必须与一个Lock绑定,因此Condition一般都是作为Lock的内部实现。
await() :造成当前线程在接到信号或被中断之前一直处于等待状态。
await(long time, TimeUnit unit) :造成当前线程在接到信号、被中断或到达指定等待时间之前一直处于等待状态
awaitNanos(long nanosTimeout) :造成当前线程在接到信号、被中断或到达指定等待时间之前一直处于等待状态。返回值表示剩余时间,如果在nanosTimesout之前唤醒,那么返回值 = nanosTimeout - 消耗时间,如果返回值 <= 0 ,则可以认定它已经超时了。
awaitUninterruptibly() :造成当前线程在接到信号之前一直处于等待状态。【注意:该方法对中断不敏感】。
awaitUntil(Date deadline) :造成当前线程在接到信号、被中断或到达指定最后期限之前一直处于等待状态。如果没有到指定时间就被通知,则返回true,否则表示到了指定时间,返回返回false。
signal() :唤醒一个等待线程。该线程从等待方法返回前必须获得与Condition相关的锁。
signal()All :唤醒所有等待线程。能够从等待方法返回的线程必须获得与Condition相关的锁。