当前位置:  开发笔记 > 编程语言 > 正文

将一个线程置于休眠状态,直到另一个线程中的条件得到解决

如何解决《将一个线程置于休眠状态,直到另一个线程中的条件得到解决》经验,为你挑选了1个好方法。

以下是两个完成(我认为)同样事情的代码块.

我基本上是在尝试学习如何使用Java 1.5的并发来摆脱Thread.sleep(long).第一个示例使用ReentrantLock,第二个示例使用CountDownLatch.我想要做的就是让一个线程进入休眠状态,直到另一个线程中的条件得到解决.

ReentrantLock提供了一个布尔锁定,我用来决定是否唤醒另一个线程,然后我使用条件和等待/信号来休眠另一个线程.据我所知,我需要使用锁的唯一原因是,如果多个线程需要对boolean进行写访问.

CountDownLatch似乎提供与ReentrantLock相同的功能,但没有(不必要的?)锁.然而,感觉就像我通过初始化它只需要一次倒计时来劫持它的预期用途.我认为它应该在多个线程要处理同一个任务时使用,而不是在多个线程在等待一个任务时使用.

所以,问题:

    我在ReentrantLock代码中使用锁定"正确的东西"吗?如果我只在一个线程中写入布尔值,那么锁是否必要?只要我在唤醒任何其他线程之前重置布尔值我不会导致问题,我可以吗?

    是否有一个类似于CountDownLatch的类,我可以使用它来避免锁定(假设我应该在这个实例中避免它们),这更适合这个任务?

    有没有其他方法来改进我应该注意的代码?

例1:

import java.util.concurrent.locks.*;

public class ReentrantLockExample extends Thread {

//boolean - Is the service down?
boolean serviceDown;

// I am using this lock to synchronize access to sDown
Lock serviceLock; 
// and this condition to sleep any threads waiting on the service.
Condition serviceCondition;

public static void main(String[] args) {
    Lock l = new ReentrantLock();
    Condition c = l.newCondition(); 
    ReentrantLockExample rle = new ReentrantLockExample(l, c);

    //Imagine this thread figures out the service is down
    l.lock();
    try {
        rle.serviceDown = true;
    } finally {
        l.unlock();
    }

    int waitTime = (int) (Math.random() * 5000);
    System.out.println("From main: wait time is " + waitTime);
    rle.start();
    try {
        //Symbolizes some random time that the service takes to come back up.
        Thread.sleep(waitTime);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }

    //Imagine this thread figures out that the service is back up.
    l.lock();
    try {
        rle.serviceDown = false;
        c.signal();
    } finally {
        l.unlock();
    }

}

//Constructor
public ReentrantLockExample(Lock l, Condition c) {  
    this.serviceLock = l;
    this.serviceCondition = c; 
}

/*
 * Should wait for this imaginary service to come back online.
 */
public void run() {
    System.out.println("Thread: start awaiting");
    serviceLock.lock();
    try {
        while (isServiceDown())
        {           
            serviceCondition.await();
        }
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } finally {
        serviceLock.unlock();
    }
    System.out.println("Thread: done awaiting");
}


private boolean isServiceDown() {       
    return serviceDown;
}
}

示例二:

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.*;

public class CountDownLatchExample extends Thread {

    //boolean - Is the service down?
    boolean serviceDown;

    // I am using this latch to wait on the service.
    CountDownLatch serviceLatch; 


    public static void main(String[] args) {
        CountDownLatch cdl = new CountDownLatch(1);     
        CountDownLatchExample cdle = new CountDownLatchExample(cdl);

        //Service goes down.
        cdle.serviceDown = true;        

        int waitTime = (int) (Math.random() * 5000);
        System.out.println("From main: wait time is " + waitTime);
        cdle.start();
        try {
            //Symbolizes some random time that the service takes to come back up.
            Thread.sleep(waitTime);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        //Service comes back up.
        cdle.serviceDown = false;
        cdl.countDown();    
    }

    //Constructor 
    public CountDownLatchExample(CountDownLatch cdl) {  
        this.serviceLatch = cdl;         
    }

    /*
     * Should wait for this imaginary service to come back online.
     */
    public void run() {
        System.out.println("Thread: start awaiting");
        try {
            while (isServiceDown()) {           
                serviceLatch.await();
            }
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println("Thread: done awaiting");
    }

    private boolean isServiceDown() {       
        return serviceDown;
    }
}

Craig P. Mot.. 9

两种方法大致相同,只是CountDownLatch只能释放一次.之后所有await()调用立即返回.因此,如果您正在使用可能会出现故障的服务,CyclicBarrier实际上可能更合适.

如果您的情况确实是一次性交易,那么FutureTask会更合适.你可以调用get()来等待服务变得可用,然后你可以在get()返回后立即使用该服务.

你提到CountDownLatch允许在不使用Locks的情况下等待.但是,CountDownLatch和ReentrantLock都是使用AbstractQueuedSynchronizer实现的.在引擎盖下,它们提供相同的同步和可见性语义.



1> Craig P. Mot..:

两种方法大致相同,只是CountDownLatch只能释放一次.之后所有await()调用立即返回.因此,如果您正在使用可能会出现故障的服务,CyclicBarrier实际上可能更合适.

如果您的情况确实是一次性交易,那么FutureTask会更合适.你可以调用get()来等待服务变得可用,然后你可以在get()返回后立即使用该服务.

你提到CountDownLatch允许在不使用Locks的情况下等待.但是,CountDownLatch和ReentrantLock都是使用AbstractQueuedSynchronizer实现的.在引擎盖下,它们提供相同的同步和可见性语义.

推荐阅读
手机用户2402851155
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有