2014-11-21 50 views
0

我正在寫一個電梯控制器,目前我使用兩個線程工作:一個用於電梯物體,另一個用於人物。他們都稱呼電梯控制器類,正確地使用等待/通知命令他們的行動。我想讓它適用於多人線程和一個提升線程。所以,當第二人稱線程請求升降機時,它應該等到當前人員線程已經達到可以使用的地步。如何讓線程一次運行一個?

問題是notify()方法沒有指定哪個線程被通知..我如何克服這個問題,以便通知只通知人線程我目前正在用升降線交織而不是通知一些隨機的人線程在隊列中?

謝謝

+0

檢查我的答案和可執行例子,看它是否是你想要的。 – Jaskey 2014-11-24 10:36:19

回答

0

每個等待的線程可以有一個用戶定義的優先級。第一人在等待-1,第二人在等待-2。

您可以廣播通知,喚醒所有等待的人線程,但然後每個喚醒線程檢查自己的優先級將其優先級值減1。如果其開始處理,則它再次等待。隊列中的

0
  1. 使用多個Condition對象(可能可能與它的鎖一起)。這是什麼通知信號,但對象只有一個條件對象,所以你需要自己做。在你去之前檢查monitor

  2. 每一個線程(期待第一個線程)進入隊列並輪詢頭部,然後等待該條件。

  3. 完成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.u[email protected]191c0b76 
person1 release the lift 
person1 liftLock.unlock 
person1 signaling java.u[email protected]191c0b76 
person3 gets liftLock 
person1 finish 
person3 tring to get lockToWait of [email protected][Locked by thread person1] 
person3 get lockToWait of [email protected][Locked by thread person3] 
person3 holds the lift=========== 
person3 next notify = java.u[email protected]5115a298 
person3 release the lift 
person3 liftLock.unlock 
person4 gets liftLock 
person3 signaling java.u[email protected]5115a298 
person4 tring to get lockToWait of [email protected][Locked by thread person3] 
person3 finish 
person4 get lockToWait of [email protected][Locked by thread person4] 
person4 holds the lift=========== 
person4 next notify = java.u[email protected]31eeeaed 
person4 release the lift 
person4 liftLock.unlock 
person2 gets liftLock 
person4 signaling java.u[email protected]31eeeaed 
person2 tring to get lockToWait of [email protected][Locked by thread person4] 
person4 finish 
person2 get lockToWait of [email protected][Locked by thread person2] 
person2 holds the lift=========== 
person2 next notify = java.u[email protected]5bd44ae9 
person2 release the lift 
person2 liftLock.unlock 
person2 signaling java.u[email protected]5bd44ae9 
person2 finish