首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ReentrantLock代替CountdownLatch

ReentrantLock代替CountdownLatch
EN

Stack Overflow用户
提问于 2020-01-09 10:27:12
回答 1查看 622关注 0票数 1

我有myCountDownLatch (按预期工作):

代码语言:javascript
复制
public static void myCountDownLatch() {

    CountDownLatch countDownLatch = new CountDownLatch(1);
    Thread t = new Thread(() ->
    {
        try {
            log.info("CountDownLatch: in thread..");
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        countDownLatch.countDown();
    });
    t.start();
    try {
        countDownLatch.await();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    log.info("CountDownLatch: out thread..");
}

我试图理解CountdownLatchReentrantLock的区别,并试图用ReentrantLock而不是CountdownLatch重写myCountDownLatch

代码语言:javascript
复制
public static void myRentrantLock() {

    ReentrantLock lock = new ReentrantLock();
    Condition condition = lock.newCondition();

    Thread t = new Thread(() ->
    {
        try {
            log.info("ReentrantLock: in thread..");
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    });

    lock.lock();
    t.start();
    lock.unlock();

    log.info("ReentrantLock: out thread..");
}

只要Thread t ReentrantLock 没有使用ReentrantLock而不是 CountDownLatch**.**完成,I只想停止主线程

但是,myRentrantLock的行为并不等于我的myCountDownLatch。为什么?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-01-09 19:07:16

您不能用ReentrantLock替换倒计时锁存器,这是一个互斥和通知工具,但是您可以使用ReentrantLock实现类似的功能。

可能看起来像

代码语言:javascript
复制
public class MyLatch {
    final ReentrantLock lock = new ReentrantLock();
    final Condition zeroReached = lock.newCondition();
    int remaining;

    MyLatch(int count) {
        if(count < 0) throw new IllegalArgumentException();
        remaining = count;
    }
    public void await() throws InterruptedException {
        lock.lock();
        try {
            while(remaining != 0) zeroReached.await();
        }
        finally {
            lock.unlock();
        }
    }
    public boolean await(long timeout, TimeUnit unit) throws InterruptedException {
        lock.lock();
        try {
            if(remaining == 0) return true;
            long deadLine = System.nanoTime() + unit.toNanos(timeout);
            while(remaining != 0) {
                final long remainingTime = deadLine - System.nanoTime();
                if(remainingTime <= 0) return false;
                zeroReached.await(remainingTime, TimeUnit.NANOSECONDS);
            }
            return true;
        }
        finally {
            lock.unlock();
        }
    }
    public void countDown() {
        lock.lock();
        try {
            if(remaining > 0 && --remaining == 0) zeroReached.signalAll();
        }
        finally {
            lock.unlock();
        }
    }
    public long getCount() {
        lock.lock();
        try {
          return remaining;
        }
        finally {
            lock.unlock();
        }
    }
}

ReentrantLock保护内部状态,即remaining字段。关联的Condition zeroReached用于允许等待remaining字段变为零的线程。

这可以与内置的CountDownLatch一样使用。

代码语言:javascript
复制
public class MyLatchTest {
    public static void main(String[] args) {
        int num = 10;
        MyLatch countDownLatch = new MyLatch(num);
        for(int i = 0; i < num; i++) {
            Thread t = new Thread(() ->
            {
                try {
                    System.out.println("CountDownLatch: in thread..");
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("CountDownLatch: one thread finished..");
                countDownLatch.countDown();
            });
            t.start();
        }
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("CountDownLatch: out thread..");
    }
}

请注意,这里不需要显式的Lock,它的内在锁定特性也能工作:

代码语言:javascript
复制
public class MyLatch {
    int remaining;

    MyLatch(int count) {
        if(count < 0) throw new IllegalArgumentException();
        remaining = count;
    }
    public synchronized void await() throws InterruptedException {
        while(remaining != 0) wait();
    }
    public synchronized boolean await(long timeout, TimeUnit unit) throws InterruptedException {
        if(remaining == 0) return true;
        long deadLine = System.nanoTime() + unit.toNanos(timeout);
        while(remaining != 0) {
            long remainingTime = deadLine - System.nanoTime();
            if(remainingTime <= 0) return false;
            wait(remainingTime / 1_000_000, (int)(remainingTime % 1_000_000));
        }
        return true;
    }
    public synchronized void countDown() {
        if(remaining > 0 && --remaining == 0) notifyAll();
    }
    public synchronized long getCount() {
        return remaining;
    }
}

但无论是哪种情况,内置的CountDownLatch都是更有效的…。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59661898

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档