这是我从OCPJ SE7中挑选的例子。 一些程序如何卡在WaitForJoe类中,只有我得到的输出如下。虽然有时我得到了完整的输出。
IC1122 - 马德里到巴黎锁定列车课程
IC1122 - 马德里到巴黎:我已到达车站
IC1122 - 马德里向巴黎发送信号
在车站等待乔来的IC1122
在WaitForJoe类中的Thread-1锁定
import java.util.concurrent.locks.*;
class MyStack {
private static Lock station = new ReentrantLock();
private static Condition joeArrival = station.newCondition();
//private static Condition syncc = station.newCondition();
public static volatile boolean flag = false ;
static class Train extends Thread {
public Train(String name) {
this.setName(name);
}
public void run() {
System.out.println(getName() +" Locking in train class");
station.lock();
try {
System.out.println(getName() + ": I've arrived in station ");
if(getName().startsWith("IC1122")) {
System.out.println(getName() +" sending signal ");
while (!flag){}
joeArrival.signalAll();
}
}
finally {
System.out.println(getName() +" UnLocking in train class");
station.unlock();
}
}
}
static class WaitForJoe extends Thread {
public void run() {
System.out.println("Waiting in the station for IC1122 in which Joe is coming");
System.out.println(getName() +" Locking in WaitForJoe class");
station.lock();
System.out.println( " unlocking " + station.toString());
try {
System.out.println(getName() +" waiting !!!!");
flag = true ;
joeArrival.await();
System.out.println("Pick up Joe and go home");
} catch(InterruptedException ie) {
ie.printStackTrace();
}
finally {
System.out.println(getName() +" UnLocking in WaitForJoe class");
station.unlock();
}
}
}
public static void main(String []args) throws InterruptedException {
new Train("IC1122 - Madrid to Paris").start();
new WaitForJoe().start();
}
}
答案 0 :(得分:0)
这里的问题是,当发送信号时,没有任何东西在等待joeArrival。信令条件仅唤醒当前正在等待它的线程。在你的程序中,WaitForJoe和Train被站锁相互排除。因此,当火车锁定车站时WaitForJoe正在等待它。火车不会解锁,直到它将信号发送到joeArrival,因此WaitForJoe不会在joeArrival上等待,直到信号发送完毕为止。
当WaitForJoe线程首先获得站锁时,您可以获得完整的输出。在这种情况下,ReentrantLock在等待条件时被释放,而Train线程确实最终发出信号。
您是否考虑使用CountDownLatch来模拟此交互?它大大简化了实施......
private static CountDownLatch joeArrival = new CountDownLatch(1);
public static volatile boolean flag = false ;
static class Train extends Thread {
public Train(String name) {
this.setName(name);
}
public void run() {
System.out.println(getName() +" Locking in train class");
System.out.println(getName() + ": I've arrived in station ");
if(getName().startsWith("IC1122")) {
System.out.println(getName() +" sending signal ");
while (!flag){}
joeArrival.countDown();
}
}
}
static class WaitForJoe extends Thread {
public void run() {
System.out.println("Waiting in the station for IC1122 in which Joe is coming");
System.out.println(getName() +" Locking in WaitForJoe class");
try {
System.out.println(getName() +" waiting !!!!");
flag = true ;
joeArrival.await();
System.out.println("Pick up Joe and go home");
} catch(InterruptedException ie) {
ie.printStackTrace();
}
}
}