这里有两块代码完成(我认为是)同样的事情.
我基本上正在尝试学习如何使用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;
}
}