java中Condition类的详细介绍(详解)

更新时间:2023-06-14 03:00:08 阅读: 评论:0

java中Condition类的详细介绍(详解)
已找不到原⽂了,还望原⽂博主看到能告诉⼩⽩⼀下,⼀定标注原⽂地址
⼀ condition 介绍及demo
 Condition是在java 1.5中才出现的,它⽤来替代传统的Object的wait()、notify()实现线程间的协作,相⽐使⽤Object的wait()、
notify(),使⽤Condition的await()、signal()这种⽅式实现线程间协作更加安全和⾼效。因此通常来说⽐较推荐使⽤Condition,阻塞队列实际上是使⽤了Condition来模拟线程间协作。
Condition是个接⼝,基本的⽅法就是await()和signal()⽅法;
Condition依赖于Lock接⼝,⽣成⼀个Condition的基本代码是wCondition()
调⽤Condition的await()和signal()⽅法,都必须在lock保护之内,就是说必须在lock.lock()和lock.unlock之间才可以使⽤
  Conditon中的await()对应Object的wait();
Condition中的signal()对应Object的notify();
Condition中的signalAll()对应Object的notifyAll()。
condition常见例⼦arrayblockingqueue。下⾯是demo:
package thread;
import urrent.locks.Condition;
import urrent.locks.Lock;
import urrent.locks.ReentrantLock;
/**
*
* @author zhangliang
*
* 2016年4⽉8⽇下午5:48:54
*/
public class ConTest {
final Lock lock = new ReentrantLock();
final Condition condition = wCondition();
家庭电话
数学归纳法public static void main(String[] args) {
// TODO Auto-generated method stub
ConTest test = new ConTest();
Producer producer = w Producer();
Consumer consumer = w Consumer();
consumer.start();
producer.start();
}
class Consumer extends Thread{
@Override
public void run() {
consume();
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⽅法被带调⽤)时 ,这些等待线程才会被唤醒,从⽽重新争夺锁。
Condition实现⽣产者、消费者模式:
package thread;
import java.util.PriorityQueue;
import urrent.locks.Condition;
import urrent.locks.Lock;
import urrent.locks.ReentrantLock;
public class ConTest2 {
private int queueSize = 10;
private PriorityQueue<Integer> queue = new PriorityQueue<Integer>(queueSize);
private Lock lock = new ReentrantLock();
private Condition notFull = wCondition();
private Condition notEmpty = wCondition();
public static void main(String[] args) throws InterruptedException  {
ConTest2 test = new ConTest2();
Producer producer = w Producer();
Consumer consumer = w Consumer();
producer.start();
consumer.start();
Thread.sleep(0);
producer.interrupt();
consumer.interrupt();
}
class Consumer extends Thread{
@Override
public void run() {
consume();
}
volatile boolean flag=true;
private void consume() {
while(flag){
lock.lock();
try {
while(queue.isEmpty()){
try {
System.out.println("队列空,等待数据");
notEmpty.await();
} catch (InterruptedException e) {
flag =fal;
}
}
queue.poll();                //每次移⾛队⾸元素
我心向党
notFull.signal();
System.out.println("从队列取⾛⼀个元素,队列剩余"+queue.size()+"个元素");                } finally{
lock.unlock();
}
}
}
}
class Producer extends Thread{
@Override
public void run() {
produce();
}
volatile boolean flag=true;
private void produce() {
while(flag){
lock.lock();
try {
while(queue.size() == queueSize){
try {
System.out.println("队列满,等待有空余空间");
notFull.await();
} catch (InterruptedException e) {
flag =fal;
}
}
queue.offer(1);        //每次插⼊⼀个元素
notEmpty.signal();
System.out.println("向队列取中插⼊⼀个元素,队列剩余空间:"+(queueSize-queue.size()));
} 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,否则表⽰到了指定时间,返回返回fal。
signal() :唤醒⼀个等待线程。该线程从等待⽅法返回前必须获得与Condition相关的锁。
signal()All :唤醒所有等待线程。能够从等待⽅法返回的线程必须获得与Condition相关的锁。
三 condition实现分析:
Condition接⼝包含了多种await⽅式和两个通知⽅法
ConditionObject实现了Condition接⼝,是AbstractQueuedSynchronizer的内部类(因为Condition的操作都需要获取想关联的锁)Reentrantlock的newCondition⽅法返回与某个lock实例相关的Condition对象
public abstract class AbstractQueuedLongSynchronizer
extends AbstractOwnableSynchronizer
implements java.io.Serializable {
结合上⾯的类图,我们看到condition实现是依赖于aqs,⽽aqs是个抽象类。⾥⾯定义了同步器的基本框架,实现了基本的结构功能。只留有状态条件的维护由具体同步器根据具体场景来定制,如常见的 ReentrantLock 、 RetrantReadWriteLock和CountDownLatch 等等,
3.1 等待队列
Condition是AQS的内部类。每个Condition对象都包含⼀个队列(等待队列)。等待队列是⼀个FIFO的队列,在队列中的每个节点都包含了⼀个线程引⽤,该线程就是在Condition对象上等待的线程,如果⼀个线程调⽤了Condition.await()⽅法,那么该线程将会释放锁、构造成节点加⼊等待队列并进⼊等待状态。AQS有⼀个同步队列和多个等待队列,节点都是Node。等待队列的基本结构如下所⽰。
个性签名女
等待分为⾸节点和尾节点。当⼀个线程调⽤Condition.await()⽅法,将会以当前线程构造节点,并将节点从尾部加⼊等待队列。新增节点就是将尾部节点指向新增的节点。节点引⽤更新本来就是在获取锁以后的操作,所以不需要CAS保证。同时也是线程安全的操作。
public class ConditionObject implements Condition, java.io.Serializable {
private static final long rialVersionUID = 1173984872572414699L;
/** First node of condition queue. */
private transient Node firstWaiter;
/** Last node of condition queue. */
辽阔的反义词
private transient Node lastWaiter;
3.2 等待
当线程调⽤了Condition的await()⽅法以后。线程就作为队列中的⼀个节点被加⼊到等待队列中去了。同时会释放锁的拥有。当从await ⽅法返回的时候。当前线程⼀定会获取condition相关联的锁。
如果从队列(同步队列和等待队列)的⾓度去看await()⽅法,当调⽤await()⽅法时,相当于同步队列的⾸节点(获取锁的节点)移动到Condition的等待队列中。

本文发布于:2023-06-14 03:00:08,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/89/1037461.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:等待   线程   队列   节点   实现   状态   基本   信号
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图