Вот две части кода, которые выполняют (что я думаю) одно и то же.
В основном я пытаюсь научиться использовать Java 1.5 concurrency, чтобы уйти от Thread.sleep(long). В первом примере используется ReentrantLock, а во втором примере используется CountDownLatch. Суть того, что я пытаюсь сделать, - поставить один поток в режим сна, пока условие не будет разрешено в другом потоке.
ReentrantLock обеспечивает блокировку логического, который я использую, чтобы решить, следует ли разбудить другой поток или нет, а затем я использую условие с await/signal, чтобы спать в другом потоке. Насколько я могу судить, единственной причиной, по которой мне нужно будет использовать блокировки, является то, что для более одного потока требуется доступ на запись к логическому.
Функция CountDownLatch, как представляется, обеспечивает те же функции, что и ReentrantLock, но без блокировок (ненужных?). Тем не менее, похоже, что я как бы захватил его предполагаемое использование, инициализируя его только одним обратным отсчетом. Я думаю, что он должен использоваться, когда несколько потоков будут работать над одной задачей, а не когда несколько потоков ждут по одной задаче.
Итак, вопросы:
-
Использую ли я блокировки для "правильной вещи" в коде ReentrantLock? Если я пишу только в буле в одном потоке, нужны ли блокировки? Пока я reset логический, прежде чем просыпать любые другие потоки, я не могу вызвать проблему, могу ли я?
-
Есть ли класс, похожий на 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;
}
}