如何让线程一次运行一个?

时间:2014-11-21 04:33:56

标签: java multithreading concurrency thread-safety

我正在编写一个电梯控制器,我目前使用两个线程:一个用于电梯对象,另一个用于人物对象。它们都调用一个电梯控制器类,使用wait / notify正确地命令它们的动作。我想让它与多人线程和一个提升线程一起工作。因此,当第二人称线程请求升力时,它应该等到当前人员线程达到可接受的点。

问题是notify()方法没有指定通知哪个线程。我如何克服这个问题,以便通知只通知人员线程我当前正在与提升线程交错,而不是通知一些随机队列中的人物线程?

由于

2 个答案:

答案 0 :(得分:0)

每个等待的线程都可以具有用户定义的优先级。第一人等待 - 1,第二人等待 - 2.

您可以广播通知唤醒所有等待的人员线程,但随后每个被唤醒的线程检查其自己的优先级,将其优先级值减1。如果它为零则开始处理,否则它会再次等待。

答案 1 :(得分:0)

  1. 在队列中使用多个Condition对象(可能与其锁定一起使用)。这是通知信号,但对象只有一个条件对象,所以你需要自己做。在你离开之前检查monitor

  2. 每个线程(期望第一个线程)进入队列并轮询头部,然后等待该条件。

  3. 在Person线程完成后,发出下一个条件对象的信号(下一个线程正在等待它)。

  4. 此示例可能对您有所帮助:

    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