Google – Stop All Way
一道非常有意思的Design题。Google engineer们的脑洞也是一个比一个大。
题目很简单,就是design data structure来实现美国的stop all way路口,具体就是实现
void arriveCar(Lane lane, Car car);
Car getNextCar();
[Solution]
首先对于Car和Lane的design. 每个Lane都会有一个Queue of Car, 每个Car也会有一个Lane object.
然后对于schedule, 有两种solution。
注意考虑下多线程的情况。
[Solution #1]
第一种是round robin。1,2,3,4,四个路口,比如这次从路口1走了一辆车,下次从路口2开始扫描,看有没有车等着,有就从2走,再下次就从3开始扫。如果路口2没有车,那就看3,扫完一圈回到路口1,要是路口1有车,就走,没有,就说明此时此刻4个路口都没有车。
但是这样的解法看上去就不太合理。因为如果想象一下现实生活中的场景,其实会是一个multithreading的过程,4个路口相当于4个threads不停的有车来,而同一时间只能走一辆车,先来先走。
那么对于round robin的方法,会有bug。比如现在4个路口都没有车,然后getNextCar()和arriveCar(4, car)被两个threads同时call,那按照上面说的从0开始扫,发现没车,到1,结果这时候又有一个thread call arriveCar(3, car), 那么这样的情况扫到路口3的时候发现有车,就会让路口3的车先走。但事实却是路口4的车先到。
[Solution #2]
Maintain一个queue来记录schedule的顺序,在getNextCar()的时候只要poll出queue里的第一辆车就可以了.
当arriveCar(Lane lane, Car car)的时候,如果当前lane里一辆车都没有,把新来的这辆车offer进schedule queue. 否则只需要offer进当前路口自己的queue就可以了。
当getNextCar()之后,将next car所属车道的下一辆车offer进schedule queue。
这样即可以保证先到先走的顺序,用一个BlockingQueue也可以解决multithreading的情况。
 
 
 
 
Read full article from Google – Stop All Way
一道非常有意思的Design题。Google engineer们的脑洞也是一个比一个大。
题目很简单,就是design data structure来实现美国的stop all way路口,具体就是实现
void arriveCar(Lane lane, Car car);
Car getNextCar();
[Solution]
首先对于Car和Lane的design. 每个Lane都会有一个Queue of Car, 每个Car也会有一个Lane object.
然后对于schedule, 有两种solution。
注意考虑下多线程的情况。
[Solution #1]
第一种是round robin。1,2,3,4,四个路口,比如这次从路口1走了一辆车,下次从路口2开始扫描,看有没有车等着,有就从2走,再下次就从3开始扫。如果路口2没有车,那就看3,扫完一圈回到路口1,要是路口1有车,就走,没有,就说明此时此刻4个路口都没有车。
但是这样的解法看上去就不太合理。因为如果想象一下现实生活中的场景,其实会是一个multithreading的过程,4个路口相当于4个threads不停的有车来,而同一时间只能走一辆车,先来先走。
那么对于round robin的方法,会有bug。比如现在4个路口都没有车,然后getNextCar()和arriveCar(4, car)被两个threads同时call,那按照上面说的从0开始扫,发现没车,到1,结果这时候又有一个thread call arriveCar(3, car), 那么这样的情况扫到路口3的时候发现有车,就会让路口3的车先走。但事实却是路口4的车先到。
[Solution #2]
Maintain一个queue来记录schedule的顺序,在getNextCar()的时候只要poll出queue里的第一辆车就可以了.
当arriveCar(Lane lane, Car car)的时候,如果当前lane里一辆车都没有,把新来的这辆车offer进schedule queue. 否则只需要offer进当前路口自己的queue就可以了。
当getNextCar()之后,将next car所属车道的下一辆车offer进schedule queue。
这样即可以保证先到先走的顺序,用一个BlockingQueue也可以解决multithreading的情况。
class Car {  int id;  Lane lane;     public Car(int id, Lane lane) {    this.id = id;    this.lane = lane;  }   }   class Lane {  Queue<Car> queue;  int id;     public Lane(int id) {    this.id = id;    this.queue = new LinkedList<>();  }}// round robin - not survive multithreadingclass Solution {     List<Lane> lanes = new ArrayList<>();  lanes.add(new Lane(0));   lanes.add(new Lane(1));   lanes.add(new Lane(2));   lanes.add(new Lane(3));   int currLane = 0;       public void arriveCar(Car car, Lane lane) {    if (car == null || lane == null) {      return;    }    lane.queue.offer(car);  }     // round robin - not survive multithreading  // 比如现在所有车道都没有车,currlane在0。  // 然后getNextCar()和arriveCar(car, 4)同时被两个threads call  // currlane从0开始循环,循环到1车道的时候又有另个一thread call了arriveCar(car, 3)  // 结果会变成3车道的车比4车道的车先走,但事实是4车道的车先到。  public Car getNextCar() {    Car result = null;    int tmp = currLane;    while (lanes.get(tmp).queue.isEmpty()) {      tmp = (tmp + 1) % 4;      if (tmp == currLane) {        break;      }    }    if (!lanes.get(tmp).queue.isEmpty()) {      result = lanes.get(tmp).poll();      currLane = (tmp + 1) % 4;    }         return result;  }}class Solution2 {  Lane lane0 = new Lane(0);  Lane lane1 = new Lane(1);  Lane lane0 = new Lane(2);  Lane lane1 = new Lane(3);     Queue<Car> next = new LinkedList<>();        public void arriveCar(Car car, Lane lane) {    if (car == null || lane == null) {      return;    }         if (lane.queue.isEmpty()) {      next.offer(car);    }    car.lane = lane;    lane.queue.offer(car);  }     public Car getNext() {    if (next.isEmpty()) {      return null;    }         Car result = next.poll();    result.lane.queue.poll();    if (!result.lane.queue.isEmpty()) {      next.offer(result.lane.queue.peek());    }         return result;  }}