Command Palette

Search for a command to run...

PHASE 4Intermediate ~14 min· topic 5 of 18Level 2

Problem 4.5 — Elevator

In one line

State + scheduling + concurrency + request handling. The harder LLD: multiple elevators moving between floors with internal and external requests.

0/18 · 0%

Think of it like this

An elevator in a busy office building. It doesn't run to every floor one at a time in the order buttons were pressed; it tries to serve everyone efficiently by going up, stopping wherever needed, then going back down. That 'sweep' strategy is called SCAN.

Key ideas

  1. 01

    States per elevator: Idle, MovingUp, MovingDown, DoorOpen, Maintenance.

  2. 02

    Requests: internal (floor buttons inside car) + external (up/down call buttons per floor).

  3. 03

    Scheduling policy: SCAN (elevator algorithm — go up serving stops, then down serving stops) vs nearest-first vs FCFS.

  4. 04

    Direction discipline: an elevator serving upward stops ignores downward external calls to reduce thrashing.

  5. 05

    Concurrency risk: the elevator state and pending-request set are shared mutation — guard both with one lock.

  6. 06

    A controller dispatches requests to elevators (picking closest/idle/best-fit); each elevator runs its own loop.

  7. 07

    Edge cases: door reopen (obstruction), capacity limit, maintenance mode draining stops.

Java / Spring map

  • →

    ElevatorController with a ScheduledExecutorService per elevator; a ReentrantLock around elevator state.

Code & diagrams

ScanVsFcfsdiagram

SCAN sweeps in one direction and serves everything on the way — FCFS zig-zags and wastes floors.

Rendering diagram…
ElevatorController.javajava

SCAN dispatch with a shared, lock-protected request set.

public class Elevator {
  public enum Dir { IDLE, UP, DOWN }

  private int floor = 0;
  private Dir dir = Dir.IDLE;
  private final TreeSet<Integer> stops = new TreeSet<>(); // sorted → SCAN

  public synchronized void push(int target) {
    stops.add(target);
    if (dir == Dir.IDLE) dir = target > floor ? Dir.UP : Dir.DOWN;
  }

  // called by a single controller loop tick
  public synchronized void tick() {
    if (stopAt(floor)) {
      stops.remove(floor);
      System.out.println("~ floor " + floor + " (door open)");
    }
    Integer next = nextStop();
    if (next == null) { dir = Dir.IDLE; return; }
    floor += dir == Dir.UP ? 1 : -1;        // move one floor per tick
    if (!hasRequestsAhead()) dir = dir == Dir.UP ? Dir.DOWN : Dir.UP; // reverse at end
  }

  private boolean hasRequestsAhead() {
    return dir == Dir.UP ? stops.ceiling(floor + 1) != null
                         : stops.floor(floor - 1) != null;
  }
  private Integer nextStop() {
    return dir == Dir.UP ? stops.ceiling(floor) : stops.floor(floor);
  }
  private boolean stopAt(int f) { return stops.contains(f); }
}

// External calls: controller picks the best elevator (e.g. nearest & same/IDLE direction).
public class ElevatorController {
  private final List<Elevator> cars;
  public ElevatorController(int n) {
    cars = new ArrayList<>();
    for (int i = 0; i < n; i++) cars.add(new Elevator());
  }
  public void call(int fromFloor, boolean up) {
    Elevator best = null;
    int bestDist = Integer.MAX_VALUE;
    for (Elevator e : cars) {                 // naive nearest-first
      int d = Math.abs(e.floor() - fromFloor);
      if (d < bestDist) { best = e; bestDist = d; }
    }
    best.push(fromFloor);
  }
}

Explain without notes

01

Why does SCAN beat nearest-first for utilization under high call density?

02

What deadlock can appear if 'door open' and 'new requests' are not synchronized together?

Practice

01

Add DoorOpen state with automatic closing after 5s, and an obstruction interlock.

02

Simulate 3 elevators X 40 floors: write a tiny scheduling simulator and compare SCAN vs FCFS.

Trade-offs

  • ↔

    SCAN = fairness + high throughput; nearest-first = better single-user latency. Both are valid — say which NFR you chose.

Completion checklist

  • I can design one elevator's state machine and a controller dispatch without notes.

Back to phase