В интервью меня попросили разработать систему бронирования билетов в кино для одновременных пользователей. Я никогда не использовал многопоточность. Требование заключалось в том, что 2 одновременных пользователя пытались использовать систему.
Скажите, что U1 и U2 выбирают одно и то же шоу.
U1 запрашивает и получает все доступные места для этого шоу.
U1 выбирает группу мест и переходит к оплате.
U2 запрашивает и получает все доступные места для этого шоу. U2 не должен видеть места, выбранные U1 как ДОСТУПНЫЕ. Платеж для U1 прошел успешно.
U1 получает билет с подтвержденными местами.
Есть и другие сценарии, но если я смогу сделать один, возможно, я смогу сделать и другие.
public class Show {
private String movieName;
private String startTime;
private String duration;
private String screenNumber;
private List<Integer> seats;
// getter and setters here...
public Show() {
seats = new ArrayList<>();
for (int i = 1; i <= 10; i++) {
seats.add(i);
}
}
//books the seats selected for a user and a show
public synchronized boolean bookSeats(String userName, int userId, List<Integer>
chosenSeats) {
for (int chosenSeat : chosenSeats) {
if (seats.get(chosenSeat) > 10) {
System.out.println("seats already taken");
return false;
}
seats.set(chosenSeat, userId);
}
return true;
}
//checks for the available seats.
public synchronized List<Integer> getBookedSeats() {
List<Integer> bookedSeats = new ArrayList<>();
for (int i = 0; i < seats.size(); i++) {
if (seats.get(i) > 10) {
bookedSeats.add(i);
}
}
return bookedSeats;
}
}
Класс пользователя
public class User implements Runnable {
private String userName;
private int userId;
private ReentrantLock lock = new ReentrantLock();
private Show show;
private List<Integer> seats;
// getter and setters here...
@Override
public void run() {
lock.lock();
try {
System.out.println(this.userName + "seleting the shows");
Show show = this.show;
System.out.println(this.userName + "Select the seats");
List<Integer> bookingSeats = this.seats;
boolean isBooked = show.bookSeats(this.userName, this.userId, bookingSeats);
if (isBooked) {
System.out.println(this.userName + "seats booked Successfully");
} else {
System.out.println(this.userName + "Please select other seats");
}
} finally {
lock.unlock();
}
}
}
класс драйвера:
public static void main(String[] args) {
Theater theater = new Theater();
List<Show> shows = new ArrayList<>();
Show show1 = new Show();
show1.setDuration("2");
show1.setMovieName("Movie1");
show1.setScreenNumber("1");
show1.setStartTime("1100");
shows.add(show1);
theater.setShow(shows);
User user1 = new User();
user1.setUserName("user1");
user1.setUserId(15);
User user2 = new User();
user2.setUserName("user2");
user2.setUserId(18);
user1.setShow(show1);
user2.setShow(show1);
user1.setSelectedSeats(Arrays.asList(2, 4));
user2.setSelectedSeats(Arrays.asList(2, 4));
new Thread(user1).start();
new Thread(user2).start();
}
}
Мой код не был принят.
а. Если кто-нибудь может объяснить мне, как это еще развязать?
б. Я чувствую, что все привязано к пользователю. Означает, что если я хочу заниматься отдельными видами деятельности, например, чем я занимаюсь run
функцию, которую я мог бы выполнить в классе драйвера последовательно, введя мои данные: U1 проверяет билеты … U2 книжный билет и т.д. и т.д. или мое предположение неверно?
c. это потокобезопасный код? Как я могу запустить это, когда несколько пользователей пытаются забронировать билет?
d. Нужно ли мне использовать список массивов Threadsafe?
е. Как я могу реализовать глобальный счетчик сеансов, срок действия которого может истечь, если пользователю требуется длительное время ожидания? Если я засыпаю нить run
функция (чтобы поток превысил глобальный счетчик сеансов) не заставит ли это спать все потоки?
Заранее спасибо.