Переведите один поток в спящий режим, пока условие не будет разрешено в другом потоке.

Вот два куска кода, которые выполняют (что я думаю) одно и то же.

Я в основном пытаюсь научиться использовать параллелизм Java 1.5, чтобы уйти от Thread.sleep (long). Первый пример использует ReentrantLock, а второй пример использует CountDownLatch. Суть того, что я пытаюсь сделать, это уложить один поток в спящий режим, пока условие не будет решено в другом потоке.

ReentrantLock обеспечивает блокировку для логического значения, которое я использую, чтобы решить, следует ли пробуждать другой поток или нет, а затем я использую Условие с ожиданием / сигналом для сна другого потока. Насколько я могу судить, единственная причина, по которой мне нужно было бы использовать блокировки, заключается в том, что доступ к записи логического значения требовался более чем одному потоку.

Кажется, что CountDownLatch обеспечивает ту же функциональность, что и ReentrantLock, но без (ненужных?) Блокировок. Тем не менее, я чувствую, что я как бы угоняю его предполагаемое использование, инициализируя его только одним необходимым обратным отсчетом. Я думаю, что он должен использоваться, когда несколько потоков будут работать над одной и той же задачей, а не когда несколько потоков ожидают выполнения одной задачи.

Итак, вопросы:

Использую ли я блокировки для «правильных вещей» в коде ReentrantLock? Если я пишу только логическое значение в одном потоке, нужны ли блокировки? До тех пор, пока я перезагружаю логическое значение перед пробуждением любых других потоков, я не могу вызвать проблемы, могу ли я?

Существует ли класс, аналогичный CountDownLatch, который я могу использовать, чтобы избежать блокировок (при условии, что в этом случае я должен избегать их), который более естественно подходит для этой задачи?

Есть ли другие способы улучшить этот код, о которых мне следует знать?

ПЕРВЫЙ ПРИМЕР:

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;
    }
}

Ответы на вопрос(3)

Ваш ответ на вопрос