Java 承载力等于N的滑雪升降机。

Java 承载力等于N的滑雪升降机。,java,multithreading,Java,Multithreading,我正在学习多线程。这是我的第一项任务。我写了这段代码,我不能继续了。任务: 容量等于N的滑雪升降机。 客户机有一个权重(随机Ki值),它们是在中执行的线程 循环: 下坡(睡眠(大随机值) 试着进入电梯(如果客户的总重量 小于或等于N) 如果失败-他们正在等待(睡眠(小随机值) 并重新执行上一点 如果成功的话,它们就会上升 } 我有三个问题无法解决: 第一个要进入的人必须是第一个试图进入的人。(就像在队列中一样) 第一个上电梯的客户也必须是第一个下电梯的客户 我的程序中的监视器是什么 提前感谢

我正在学习多线程。这是我的第一项任务。我写了这段代码,我不能继续了。任务:

容量等于N的滑雪升降机。 客户机有一个权重(随机Ki值),它们是在中执行的线程 循环:

  • 下坡(睡眠(大随机值)
  • 试着进入电梯(如果客户的总重量 小于或等于N)
  • 如果失败-他们正在等待(睡眠(小随机值) 并重新执行上一点
  • 如果成功的话,它们就会上升

    }
  • 我有三个问题无法解决:

  • 第一个要进入的人必须是第一个试图进入的人。(就像在队列中一样)
  • 第一个上电梯的客户也必须是第一个下电梯的客户
  • 我的程序中的监视器是什么

  • 提前感谢:)

    显然,系统中的瓶颈是lift。lift只能有N个并发用户

    另外,3.提到了监视器。在阅读了监视器是什么之后,你应该明白它允许独占访问有限的资源,电梯


    因此,请设计电梯通道,尝试获取N个监视器中的一个,等待片刻,最后不要忘记释放监视器,以便其他人可以获取它。

    我认为这个问题属于

    您的客户应该有一个状态,如“topofthemountaninreached”、“liftstationreacted”、“liftEntered”

    然后,您的客户机等待此事件发生。这也是您要监视哪个元素的问题的答案-状态或客户机本身

    对于队列,可以使用
    ArrayListBlockingQueue
    。 然后,您的SkiLift必须等待新客户到达并将其放入电梯。客户进入电梯后,电梯还会通知客户其已进入电梯。到达电梯顶部时,电梯还会通知客户

    下面是这样一个解决方案的示例。 它使用Java Executor服务来安排事件,以使客户机离开电梯,并到达下坡段末端的电梯站。这也可以以不同的方式解决

    客户:

    package skilift;
    
    import java.util.ArrayList;
    import java.util.concurrent.ArrayBlockingQueue;
    import java.util.concurrent.Executors;
    import java.util.concurrent.ScheduledExecutorService;
    import java.util.concurrent.TimeUnit;
    
    public class SkiLift implements Runnable{
    
        private ScheduledExecutorService getOutClientExecutor;
    
        public SkiLift() {
            getOutClientExecutor = Executors.newScheduledThreadPool(50);
            waitingClientsQueue = new ArrayBlockingQueue<>(1000);
            occupiedSeats = new ArrayList<>();
        }
    
        private final ArrayList<Client> occupiedSeats; 
    
        private long usedCapacity;
    
        private final ArrayBlockingQueue<Client> waitingClientsQueue;
    
        private final long capacity = 500;
    
        public void add(Client client) {
            synchronized(waitingClientsQueue) {
                waitingClientsQueue.add(client);
                waitingClientsQueue.notify();
            }
    
        }
    
    
        private synchronized void occupySeat(Client client) {
            occupiedSeats.add(client);
            usedCapacity += client.weight;
        }
    
        private synchronized void getClientOut(Client client) {
            occupiedSeats.remove(client);
            usedCapacity -= client.weight;
    
            // notify the waitingClientQueue that the capacity has changed
            synchronized (waitingClientsQueue) {
                waitingClientsQueue.notify();
            }
    
            client.topReached();
        }
    
    
        public void run() {
            while (true) {
                synchronized(waitingClientsQueue) {
                    try {
    
                        if (!waitingClientsQueue.isEmpty()) {
                            Client c = waitingClientsQueue.peek();
                            if (usedCapacity + c.weight <= capacity) {
                                occupySeat(waitingClientsQueue.poll());
                                getOutClientExecutor.schedule(() -> {
                                    getClientOut(c);
                                }, 2, TimeUnit.SECONDS);
                            } else {
                                waitingClientsQueue.wait();
                            }
                        } else {
                            waitingClientsQueue.wait();
                        }
    
                    } catch (InterruptedException ie) {
                        Thread.currentThread().interrupt();
                    }
                }
            }
        }
    
    }
    
    电梯:

    package-skilift;
    导入java.util.ArrayList;
    导入java.util.concurrent.ArrayBlockingQueue;
    导入java.util.concurrent.Executors;
    导入java.util.concurrent.ScheduledExecutorService;
    导入java.util.concurrent.TimeUnit;
    公共类SkiLift实现可运行{
    私有ScheduledExecutorService getOutClientExecutor;
    公共升降机(){
    getOutClientExecutor=Executors.newScheduledThreadPool(50);
    waitingClientsQueue=新的ArrayBlockingQueue(1000);
    OccuppiedSeats=新ArrayList();
    }
    私人最终ArrayList占用座位;
    私人长期使用能力;
    专用最终阵列锁定队列等待客户端队列;
    私人最终长期容量=500;
    公共作废添加(客户端){
    已同步(waitingClientsQueue){
    waitingclientsque.add(客户端);
    waitingclientsque.notify();
    }
    }
    专用同步无效占用席位(客户端){
    占用座位。添加(客户);
    usedCapacity+=客户端重量;
    }
    私有同步的void getClientOut(客户端){
    占用座位。移除(客户);
    使用容量-=客户重量;
    //通知waitingClientQueue容量已更改
    已同步(waitingClientsQueue){
    waitingclientsque.notify();
    }
    client.topreach();
    }
    公开募捐{
    while(true){
    已同步(waitingClientsQueue){
    试一试{
    如果(!waitingclientsquee.isEmpty()){
    客户端c=waitingclientsquee.peek();
    如果(使用容量+c.重量){
    getClientOut(c);
    },2,时间单位(秒);
    }否则{
    waitingclientsque.wait();
    }
    }否则{
    waitingclientsque.wait();
    }
    }捕获(中断异常ie){
    Thread.currentThread().interrupt();
    }
    }
    }
    }
    }
    
    import java.util.Random;
    import java.util.concurrent.Executors;
    import java.util.concurrent.ScheduledExecutorService;
    import java.util.concurrent.TimeUnit;
    
    public class Client implements Runnable{
    
        final ScheduledExecutorService dhexceutors = Executors.newScheduledThreadPool(500);
    
        final static Random DHRANDOM = new Random();
    
        final long weight;
    
        public enum State {
            goDownhill,
            waitForLift,
            goUp,
            onTop,
        }
    
        private State state;
    
        public SkiLift lift; 
    
        public Client(long weight,SkiLift lift) {
            this.lift = lift;
            this.weight = weight;
            this.state = State.onTop;
            goDownHill();
        }
    
        private void enterLift() {
            lift.add(this);
        }
    
    
        private void goDownHill() {
            synchronized (this) {
                state = State.goDownhill;
                this.notify();
            }
            dhexceutors.schedule(() -> {
                liftStationReached();
            }, DHRANDOM.nextInt(500), TimeUnit.MILLISECONDS); 
        }
    
        public void liftStationReached() {
            synchronized(this) {
                state = State.waitForLift;
                this.notify();
            }
        }
    
    
        public void topReached() {
            synchronized(this) {
                state = State.onTop;
                this.notify();
            }
        }
    
        public void liftEntered() {
            synchronized(this) {
                state = State.goUp;
                this.notify();
            }
        }
    
    
        public void run() {
            synchronized(this) {
                while (true) {
                    try {
                        this.wait();
    
                        switch (state) {
                        case waitForLift:
                            enterLift();
                            break;
                        case goUp: 
                            // just wait for the topReached event
                            break;
                        case goDownhill:
                            // just wait for reaching the lift.
                            break;
                        case onTop: 
                            goDownHill();
                            break;
                        }
    
                    } catch (InterruptedException ie) {
                        Thread.currentThread().interrupt();
                    }
                }
            }
        }
    
    }
    
    package skilift;
    
    import java.util.ArrayList;
    import java.util.concurrent.ArrayBlockingQueue;
    import java.util.concurrent.Executors;
    import java.util.concurrent.ScheduledExecutorService;
    import java.util.concurrent.TimeUnit;
    
    public class SkiLift implements Runnable{
    
        private ScheduledExecutorService getOutClientExecutor;
    
        public SkiLift() {
            getOutClientExecutor = Executors.newScheduledThreadPool(50);
            waitingClientsQueue = new ArrayBlockingQueue<>(1000);
            occupiedSeats = new ArrayList<>();
        }
    
        private final ArrayList<Client> occupiedSeats; 
    
        private long usedCapacity;
    
        private final ArrayBlockingQueue<Client> waitingClientsQueue;
    
        private final long capacity = 500;
    
        public void add(Client client) {
            synchronized(waitingClientsQueue) {
                waitingClientsQueue.add(client);
                waitingClientsQueue.notify();
            }
    
        }
    
    
        private synchronized void occupySeat(Client client) {
            occupiedSeats.add(client);
            usedCapacity += client.weight;
        }
    
        private synchronized void getClientOut(Client client) {
            occupiedSeats.remove(client);
            usedCapacity -= client.weight;
    
            // notify the waitingClientQueue that the capacity has changed
            synchronized (waitingClientsQueue) {
                waitingClientsQueue.notify();
            }
    
            client.topReached();
        }
    
    
        public void run() {
            while (true) {
                synchronized(waitingClientsQueue) {
                    try {
    
                        if (!waitingClientsQueue.isEmpty()) {
                            Client c = waitingClientsQueue.peek();
                            if (usedCapacity + c.weight <= capacity) {
                                occupySeat(waitingClientsQueue.poll());
                                getOutClientExecutor.schedule(() -> {
                                    getClientOut(c);
                                }, 2, TimeUnit.SECONDS);
                            } else {
                                waitingClientsQueue.wait();
                            }
                        } else {
                            waitingClientsQueue.wait();
                        }
    
                    } catch (InterruptedException ie) {
                        Thread.currentThread().interrupt();
                    }
                }
            }
        }
    
    }