利用ReentrantLock的Condition实现线程之间的通信

Condition可以实现线程之间的通信,通过awat和signal两个方法来实现线程之间的通信协作。

现在我们利用Condition来实现一个功能:开启3个线程,让线程按顺序循环打印 A、B、C。

主代码如下:

static final ReentrantLock lock = new ReentrantLock();
    static AtomicBoolean firstA = new AtomicBoolean(true);
    static class PrintRunable implements Runnable{

        private String str;
        private Condition await;
        private Condition signal;

        public PrintRunable(String str, Condition await, Condition signal) {
            this.str = str;
            this.await = await;
            this.signal = signal;
        }

        @Override
        public void run() {
            //第一次要打印A时,是没有任何人通知的
            if (firstA.get() && "A".equals(str)) {
                lock.lock();
                try {
                    System.out.println(str);
                    firstA.getAndSet(true);
                    TimeUnit.SECONDS.sleep(1);
                    signal.signal();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }
            }
            while (true) {
                while (true) {
                    lock.lock();
                    try {
                        //等待被通知
                        await.await();
                        System.out.println(str);
                        TimeUnit.SECONDS.sleep(1);
                        //通知被等待的下一个线程
                        signal.signal();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } finally {
                        lock.unlock();
                    }
                }
            }
        }
    }
测试:

@Test
    public void reentrantLockTest() throws Exception {
        final Condition condition1 = lock.newCondition();
        final Condition condition2 = lock.newCondition();
        final Condition condition3 = lock.newCondition();

        Thread a = new Thread(new PrintRunable("A",condition1,condition2));
        Thread b = new Thread(new PrintRunable("B",condition2,condition3));
        Thread c = new Thread(new PrintRunable("C",condition3,condition1));

        b.start();
        c.start();
        a.start();
        b.join();
        a.join();
        c.join();

    }

控制台打印:

A
B
C
A
B
C
A
B
C

总结:

ReentrantLock 是独占锁,一个线程拿到锁后如果不释放,那么另外一个线程肯定是拿不到锁,所以在 lock.lock() 和 lock.unlock() 之间可能有一次释放锁的操作(同样也必然还有一次获取锁的操作)。不管take() 还是 put() ,在进入 lock.lock() 后唯一可能释放锁的操作就是 await()了。也就是说 await() 操作实际上就是释放锁,然后挂起线程,一旦条件满足就被唤醒,再次获取锁!这个有点像wait和notify了,wait也会释放锁,sleep是不会释放锁的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值