9

So I need to make an elevator simulator, and I was wondering how can I go about continuously generating people to call the elevator. I need this to go on forever. So basically a person is created and calls the elevator. All of these calls are kept track of but I think I need to keep track of the people who are actually on the elevator too.

I have a few classes Person, Elevator, ElevatorCall & ElevatorCallQueue.

  1. In Person I have a run() method which basically makes an Elevator call with the current floor and destination floor and then I have a BlockingQueue that I put the call on. This run method just runs while true.

  2. In ElevatorCall I just have getters and setters for the collection and destination floors

  3. In ElevatorCallQueue, I have variables for MAX_CALLS and numberOfPeople. I have a BlockingQueue<ElevatorCall> queue = new ArrayBlockingQueue<ElevatorCall>(MAX_CALLS) and a List<Person> I add people to the list and I run through the list and start the run() method on each person. Finally I create an elevator and provide the queue, and run it.

  4. In Elevator I have the BlockingQueue<ElevatorCalls>. I have a while(true) here also, and inside it I make an ArrayList<ElevatorCall> and then I use the BlockingQueues drainTo method using the ArrayList<ElevatorCalls> as a parameter. The rest of the run() method basically iterates through the array list and does what an elevator does, so It goes to the first pressed button, checks each floor for people and if it is a destination floor.

Right now I've gotton stuck and dont know where to go from here. I need to some how have People continiously added and calling the elevator, and have the Elevator wait if there is no more calls. Would appreciate it if anybody could help put me in the right direction. Thanks

EDIT

Here is the code to the elevator class as somebody said I should post some code. However I'm not sure what code to post so I thought I'd just put in the entire class

tshepang
  • 12,111
  • 21
  • 91
  • 136
Ayohaych
  • 5,099
  • 7
  • 29
  • 51
  • 1
    @SilviuBurcea Thanks. I tried to phrase more so using words. I usually just show the code I have but this might be a bit better :) Any suggestions? – Ayohaych Dec 24 '13 at 12:34
  • Well, no ideas at the moment for Java. However, I have used GPSS to simulate real world models in a faculty course. – Silviu Burcea Dec 24 '13 at 12:35
  • Please post some code too. If you have any error, it will be easier to spot 'em, than predict by explanation. – Seagull Dec 24 '13 at 12:35
  • 2
    You may want to try the producer / consumer pattern. – Silviu Burcea Dec 24 '13 at 12:36
  • 1
    Concurrency is maybe not the right tool especially since you need to synchronize the generation vs consumption at a certain rate. If you don't you can get overflowing buffers pretty quickly and your simulation outcome depends on the randomness of thread scheduling. A simple loop that works in "simulation steps" and generates some + consumes some would allow you to simulate step-wise. Each step counts as the same point in time so everything you do there happens "concurrently" for the observer. – zapl Dec 24 '13 at 12:38
  • 1
    Yeah, I think you are hung up on concurrency. Figure it out as a simple sequential program first. – Hot Licks Dec 24 '13 at 12:43
  • @SilviuBurcea Is that sort of like whats mentioned in this question: http://stackoverflow.com/questions/616484/how-to-use-concurrentlinkedqueue – Ayohaych Dec 24 '13 at 12:44
  • @Seagull I updated the original question and added a link to a pastebin with my Elevator class, as I'm not sure what specific code I should post to help you. – Ayohaych Dec 24 '13 at 12:45
  • @zapl The program is an assignment for a concurrent programming module. So eventually it will have to work concurrently I think – Ayohaych Dec 24 '13 at 12:45
  • @HotLicks Yeah I get what you mean. I think it's nearly working in terms of a sequential one. It detects when the elevator is on a floor with people and detects when its on a destination floor, so I can add and remove. – Ayohaych Dec 24 '13 at 12:46
  • 1
    Think about what things need to be concurrent. Each concurrent thread represents some entity that will, relatively independently, perform actions. The thread should persist as long as that entity exists as a part of the stated problem, and there should never be multiple threads representing the same entity, nor multiple independent entities represented by the same thread. What are your entities? – Hot Licks Dec 24 '13 at 12:51
  • @HotLicks Thanks for the reply. The Elevator and Person are both entities, I think the Person is basically a Producer and the Elevator is a Consumer. – Ayohaych Dec 24 '13 at 13:02
  • 1
    Producer/consumer is probably not the right model. – Hot Licks Dec 24 '13 at 13:22
  • 2
    You could add a size limited queue of People for those waiting to be added to your simulation. A thread that puts new people in there and then sleeps a random amount of time produces them. The size limit of the queue can prevent overflow of people if the simulation could not consume them in time. The elevator can consume people from a per floor queue. Threads can also wait on conditions, e.g. people waiting in queue need to wait for the elevator to be at the right floor (people wait for elevator), the elevator then needs to wait on people to enter, people then wait for the right floor to exit. – zapl Dec 24 '13 at 13:24
  • 2
    Note that your "call queue" should not be a queue. You service floors in the order you pass them, not in the order the buttons were pressed. You're probably defining your queues and such before you have the model well defined in your head. Just because a particular data type exists is no reason that you must use it. – Hot Licks Dec 24 '13 at 13:27
  • @HotLicks Yeah I get what you mean. Well with how it works now, the elevator goes towards the direction of the first call, however it checks each floor it passes if there is a person on it awaiting it, and if so it will add them. It also checks if the floor is a destination floor, if it is it removes that item from the queue – Ayohaych Dec 24 '13 at 13:32
  • @zapl Yeah the thread idea sounds like it would work. So right now i have the queue created in my main class, then I run each person thread and the elevator thread. do you suggest i make a new thread and in that threads run method add in the random additions to the queue? How would I deal with the additions? – Ayohaych Dec 24 '13 at 13:34
  • I would have a thread for each elevator, and a thread for each active person. The elevator threads would run indefinitely. The person threads would come into existence based on your random number generator, press a button, get in, press another button, get out, and then disappear. You might also have a thread (running "forever") to generate the person threads. – Hot Licks Dec 24 '13 at 18:03
  • Thread that makes people, adds them to 'size limited queue' (that's the blocking queue you already have) and let the elevator class process them – user3125280 Dec 25 '13 at 00:35
  • I've seen an elevator — in a hotel in Barcelona, as it happens — that you summon by pressing a button _outside_ that says which floor you want to go to (the source floor being obvious); there's only minimal buttons inside. I don't know how this affects the planning algorithm. – Donal Fellows Dec 25 '13 at 07:45

1 Answers1

2

I think everyone's jumped at the word concurrency very quickly - don't let it cloud your judgement. I can't speak on behalf your exact problem/criteria but an elevator goes about travelling to floors, with the only disturbance being a new person pressing a button. So, why not give elevator a method simulate(int time) that does this, and a method new_person(person p) which adds another person to the queue. Then just generate a random time interval, simulate the elevator, add a new person with random floor destination and source, and then repeat.

But you say it has to be concurrent -

Well your question seems to be where do the elevatorcalls come from?

This is an instance of the typical producer consumer pattern. What's that you ask? Well the oracle documentation for BlockingQueue gives a better example than I ever could

class Producer implements Runnable {
   private final BlockingQueue queue;
   Producer(BlockingQueue q) { queue = q; }
   public void run() {
     try {
       while (true) { queue.put(produce()); }
     } catch (InterruptedException ex) { ... handle ...}
   }
   Object produce() { ... }
 }

 class Consumer implements Runnable {
   private final BlockingQueue queue;
   Consumer(BlockingQueue q) { queue = q; }
   public void run() {
     try {
       while (true) { consume(queue.take()); }
     } catch (InterruptedException ex) { ... handle ...}
   }
   void consume(Object x) { ... }
 }

 class Setup {
   void main() {
     BlockingQueue q = new SomeQueueImplementation();
     Producer p = new Producer(q);
     Consumer c1 = new Consumer(q);
     Consumer c2 = new Consumer(q);
     new Thread(p).start();
     new Thread(c1).start();
     new Thread(c2).start();
   }
 }

Hmm.. Can you see how this relates to your problem? You've already solved half of it.

The Elevator acts as the consumer of elevatorCalls, you seem to be struggling with who produces them. This is a job for a new thread that runs an ElevatorCall producers. See if you can work the rest out.

user3125280
  • 2,779
  • 1
  • 14
  • 23
  • 1
    I honestly only answered cause I saw the buzzwords 'Java' and 'Concurrency' and thought easy reputation :) Insta-upvote. You're very welcome for any help I could give. – user3125280 Dec 24 '13 at 13:08
  • I always upvote anybody who takes the time to provide any feedback :) Well the problem is in a concurrency module so it does need to be concurrent. My Elevator class just takes a queue of the calls that were made from the ElevatorCallQueue class, so the Elevator can't really add new people. I'm not sure on how to add new people randomly from another class. – Ayohaych Dec 24 '13 at 13:10
  • 1
    I won't scrutinise the logic then - concurrency here just adds a whole new dimension of complexity. But you can't avoid it. BlockingQueue seems to be what it sounds like - can't you spawn another thread that waits random time intervals between adding a person to the thread? Java has a synchronized keywords that could help [;)](http://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html) – user3125280 Dec 24 '13 at 13:24
  • Where would I create that thread ? In the elevator class or the main class? And I would have to recheck somehow if there is another person that made a call in the Call list. – Ayohaych Dec 24 '13 at 13:30
  • 1
    Okay since I'm committed I'll actually read your code now ;) - typically you would create the other thread in main, one path would execute the elevator simulation, the other would simulate the people. It's more... symmetrical – user3125280 Dec 24 '13 at 13:31
  • Thats great thanks :) If you want to see another class just tell me and I can upload it to pastebin. Or if you want we could continue in chat! Let me know really appreciate it – Ayohaych Dec 24 '13 at 13:35
  • 1
    let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/43835/discussion-between-user3125280-and-andyohart) – user3125280 Dec 24 '13 at 13:37
  • Thanks for that hopefully you can clear some things up! – Ayohaych Dec 24 '13 at 13:40