我正在编写一个电梯控制器,我目前使用两个线程:一个用于电梯对象,另一个用于人物对象。它们都调用一个电梯控制器类,使用wait / notify正确地命令它们的动作。我想让它与多人线程和一个提升线程一起工作。因此,当第二人称线程请求升力时,它应该等到当前人员线程达到可接受的点。
问题是notify()
方法没有指定通知哪个线程。我如何克服这个问题,以便通知只通知人员线程我当前正在与提升线程交错,而不是通知一些随机队列中的人物线程?
由于
答案 0 :(得分:0)
每个等待的线程都可以具有用户定义的优先级。第一人等待 - 1,第二人等待 - 2.
您可以广播通知唤醒所有等待的人员线程,但随后每个被唤醒的线程检查其自己的优先级,将其优先级值减1。如果它为零则开始处理,否则它会再次等待。
答案 1 :(得分:0)
在队列中使用多个Condition对象(可能与其锁定一起使用)。这是通知信号,但对象只有一个条件对象,所以你需要自己做。在你离开之前检查monitor。
每个线程(期望第一个线程)进入队列并轮询头部,然后等待该条件。
在Person线程完成后,发出下一个条件对象的信号(下一个线程正在等待它)。
此示例可能对您有所帮助:
public class LiftController {
static LiftThread lift = new LiftThread();
static ReentrantLock liftLock = new ReentrantLock(true);
static Queue<Lock> q = new ConcurrentLinkedQueue<Lock>();
static boolean isLiftisAvailable() {
return lift.isAvailable();
}
static synchronized void ocupyLift() {
lift.setAvailable(false);
}
static synchronized void releaseLift() {
lift.setAvailable(true);
}
public static void main(String[] args) throws InterruptedException {
PersonThread person1 = new PersonThread("person1");
PersonThread person2 = new PersonThread("person2");
PersonThread person3 = new PersonThread("person3");
PersonThread person4 = new PersonThread("person4");
List<PersonThread> persons = Arrays.asList(person1, person2, person3,person4);
lift.start();
for (PersonThread person : persons) {
person.start();
}
}
}
class PersonThread extends Thread {
public PersonThread(String name) {
this.setName(name);
}
public void run() {
System.out.println(this.getName() + " begins");
LiftController.liftLock.lock();
System.out.println(this.getName() + " gets liftLock");
Lock lockToWait = LiftController.q.poll();
if(lockToWait!=null){
System.out.println(this.getName() + " tring to get lockToWait of "+lockToWait);
lockToWait.lock();
System.out.println(this.getName() + " get lockToWait of "+lockToWait);
Condition conditionToWait=lockToWait.newCondition();
if(conditionToWait!=null){//not the first one
while (!LiftController.isLiftisAvailable()){
try {
System.out.println(this.getName()+" awaiting = "+conditionToWait);
conditionToWait.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
try {
System.out.println(this.getName() + " holds the lift===========");
LiftController.q.add(new ReentrantLock());
Lock lockToNofity=LiftController.q.peek();
lockToNofity.lock();
Condition conditionToNotify = LiftController.q.peek().newCondition();
System.out.println(this.getName()+" next notify = "+conditionToNotify);
System.out.println(this.getName() + " release the lift");
LiftController.ocupyLift();
LiftController.releaseLift();
LiftController.liftLock.unlock();
System.out.println(this.getName() + " liftLock.unlock");
if(conditionToNotify!=null){
System.out.println(this.getName()+" signaling "+conditionToNotify);
conditionToNotify.signal();
lockToNofity.unlock();
}
}
finally {
if(lockToWait!=null)
lockToWait.unlock();
System.out.println(this.getName() + " finish");
}
}
}
class LiftThread extends Thread {
private volatile boolean isAvailable = false;
public synchronized boolean isAvailable() {
return isAvailable;
}
public synchronized void setAvailable(boolean available) {
isAvailable = available;
}
public void run() {
int random = new Random().nextInt(3)+1;
while (true)
try {
// System.out.println("---------lift is doing his job-----------");
Thread.sleep(random * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
输出:
person1 begins
person1 gets liftLock
person1 holds the lift===========
person3 begins
person4 begins
person2 begins
person1 next notify = java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject@191c0b76
person1 release the lift
person1 liftLock.unlock
person1 signaling java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject@191c0b76
person3 gets liftLock
person1 finish
person3 tring to get lockToWait of java.util.concurrent.locks.ReentrantLock@24cc0f9f[Locked by thread person1]
person3 get lockToWait of java.util.concurrent.locks.ReentrantLock@24cc0f9f[Locked by thread person3]
person3 holds the lift===========
person3 next notify = java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject@5115a298
person3 release the lift
person3 liftLock.unlock
person4 gets liftLock
person3 signaling java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject@5115a298
person4 tring to get lockToWait of java.util.concurrent.locks.ReentrantLock@6365d2be[Locked by thread person3]
person3 finish
person4 get lockToWait of java.util.concurrent.locks.ReentrantLock@6365d2be[Locked by thread person4]
person4 holds the lift===========
person4 next notify = java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject@31eeeaed
person4 release the lift
person4 liftLock.unlock
person2 gets liftLock
person4 signaling java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject@31eeeaed
person2 tring to get lockToWait of java.util.concurrent.locks.ReentrantLock@3c818737[Locked by thread person4]
person4 finish
person2 get lockToWait of java.util.concurrent.locks.ReentrantLock@3c818737[Locked by thread person2]
person2 holds the lift===========
person2 next notify = java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject@5bd44ae9
person2 release the lift
person2 liftLock.unlock
person2 signaling java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject@5bd44ae9
person2 finish