Вот два куска кода, которые выполняют (как мне кажется, одно и то же).
Я в основном пытаюсь научиться использовать параллелизм 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;
}
}