java.util.concurrent并发包之Condition

本文介绍了Java中的Condition接口,它是线程间协作的重要工具,常与Lock配合使用。Condition允许线程在满足特定条件时等待,通过signal()和signalAll()方法唤醒等待线程。在示例中展示了两个线程如何通过Condition协调执行特定任务,确保线程A先执行123,线程B执行456,然后线程A再执行789。Condition的使用避免了死锁,实现了线程间的同步和通信。
摘要由CSDN通过智能技术生成

一、Condition接口

Condition可以通俗的理解为条件队列;
当一个线程在调用await方法以后,直到线程等待的某个条件为真的时候,待会被唤醒;
这种线程为简单的等待/通知模式;
Condition必须和Lock配合使用,因为共享状态变量的访问发生在多线程环境下;

final Lock lock = new ReentrantLock();
final Condition ThreeConditon = lock.newCondition();
final Condition SixConditon = lock.newCondition();

二、Condition接口中的方法

//当前线程在接到信号或者被中断之前一直处在等待状态
void await() throws InterruptedException;
//当前线程在接到信号之前一直处于等待状态
void awaitUninterruptibly();
//当前线程在接到信号、中断或者在制定的时间之前一直在等待状态。
//返回值long表示的剩余时间。
//如果在nanosTimeout之前被唤醒,那么返回值=nanosTimeout-消耗时间
//如果返回值小于0,可以认为它超时了
long awaitNanos(long nanosTimeout) throws InterruptedException;
//当前线程在接到信号、中断或者在制定的时间之前一直在等待状态。
boolean await(long time, TimeUnit unit) throws InterruptedException;
//当前线程在接到信号、中断或者在制定的时间之前一直在等待状态。
//如果没有到指定时间,则返回true,否则返回false
boolean awaitUntil(Date deadline) throws InterruptedException;
//唤醒等待线程。
//该线程的从等待方法返回前必须获得与Condition相关的lock
void signal();
//换新所有的等待线程
void signalAll();

三、总结

调用await方法后,将当前线程加入到Condition等待队列中;
当前队列释放lock,否则别的线程无法得到锁,而造成死锁;
自旋 while 挂起,不断的检查节点是否同步在队列中;
如果是,则获取lock;
否则挂起;
当线程被signal方法唤醒;
被唤醒的线程将从await方法中的while循环中退出来;
然后调用acquireQueue方法中竞争同步状态;

四、栗子:两个计数线程,同时启动,线程A执行123,线程B执行456,然后线程A执行789,结束。

public class ConcurrentTest {
    
    static class NumberWrapper{
        public int value = 1;
    }

    public static void main(String... args) {
        //初始化可重入锁
        //await和signal的Lock是同一个Lock
        final Lock lock = new ReentrantLock();

        //当屏幕上输出3时,lock.newCondition()
        final Condition reachThreeConditon = lock.newCondition();
        //当屏幕上输出6时,lock.newCondition()
        final Condition reachSixConditon = lock.newCondition();

        //NumberWrapper只是为了封装一个数字,一边可以数字对象共享,并可以设置为final
        //注意这里不要用Integer,因为Integer是不可比变对象
        final NumberWrapper num = new NumberWrapper();

        Thread threadA = new Thread(() -> {
            //需要先获得锁
            lock.lock();
            System.out.println("ThreadA获得Lock");

            try{
               System.out.println("ThreadA start write");
                while (num.value <= 3) {
                    System.out.println(num.value);
                    num.value++;
                }
                //输出到3的时候告诉B线程可以开始了
                reachThreeConditon.signal();
            } finally {
                lock.unlock();
                System.out.println("ThreadA 释放锁");
            }

            lock.lock();
            System.out.println("ThreadA获得Lock");
            try{
                //等待6输出的条件
                reachSixConditon.await();
                System.out.println("ThreadA start write");
                while (num.value <= 9) {
                    System.out.println(num.value);
                    num.value++;
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
                System.out.println("ThreadA 释放锁");
            }

        });

        Thread threadB = new Thread(() -> {
            try {
                lock.lock();
                System.out.println("ThreadB获得lock");
                Thread.sleep(5000);
                while (num.value <=3) {
                    //等待A线程输出3完毕的信号
                    reachThreeConditon.await();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                System.out.println("ThreadB释放lock");
                lock.unlock();
            }
            try {
                lock.lock();
                System.out.println("ThreadB获得lock");
                System.out.println("ThreadB start write");
                while (num.value <= 6) {
                    System.out.println(num.value);
                    num.value++;
                }
                reachSixConditon.signal();
            } finally {
                System.out.println("ThreadB释放lock");
                lock.unlock();
            }
        });

        threadB.start();
        threadA.start();
    }
}

运行结果:

ThreadB获得lock
ThreadA获得Lock
ThreadA start write
1
2
3
ThreadA 释放锁
ThreadA获得Lock
ThreadB释放lock
ThreadB获得lock
ThreadB start write
4
5
6
ThreadB释放lock
ThreadA start write
7
8
9
ThreadA 释放锁
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值