Ticket allocation system

33 Views Asked by At

i'm reading an article about ticket allocation system that deals with concurrency (of course) Here is the link :ticket I find one part that's difficult to comprehend. In the QueueService class, the method "attemptPurchase" is sequential, not concurrent. meaning that only when a user finishes purchasing a ticket that the next can. So, my question is why the need for the "lock" in the Ticket class and the tryLock method, because after each execution of the method "attemptPurchase" the ticket is removed from the list which means the next user will only interact on the list without removing tickets. Here is the Ticket class :

public class Ticket {
    private final int id;
    private AtomicBoolean locked = new AtomicBoolean(false);

    public Ticket(int id) {
        this.id = id;
    }

    public int getId() {
        return id;
    }

    public boolean isLocked() {
        return locked.get();
    }

    public boolean tryLock() {
        return locked.compareAndSet(false, true);
    }
}

Here is the QueueService class :

public class QueueService {
    private final WaitingRoomService waitingRoomService;
    private final List<Ticket> tickets;

    /**
     * Initializes a new QueueService instance.
     *
     * @param waitingRoomService the service to manage the waiting room
     * @param tickets the list of tickets available for sale
     */
    public QueueService(WaitingRoomService waitingRoomService, List<Ticket> tickets) {
        this.waitingRoomService = waitingRoomService;
        this.tickets = new CopyOnWriteArrayList<>(tickets);
    }

    /**
     * Processes the users in the waiting room, allowing them to attempt to purchase tickets.
     */
    public void processQueue() {
        waitingRoomService.getWaitingRoom().stream()
                .sorted(Comparator.comparing(User::getQueuePosition))
                .forEach(this::attemptPurchase);
    }

    /**
     * Allows the given user to attempt to purchase a ticket.
     *
     * @param user the user who will attempt to purchase a ticket
     */
    private void attemptPurchase(User user) {
        for (Ticket ticket : tickets) {
            if (ticket.tryLock()) {
                System.out.println("User " + user.getId() + " arriving at time " + user.getArrivalTime() + " purchased ticket " + ticket.getId());
                waitingRoomService.getWaitingRoom().remove(user);  // Remove user from waiting room after purchase
                tickets.remove(ticket);
                break;
            }
        }
    }
    /**
     * Returns the list of tickets.
     *
     * @return the list of tickets
     */
    public List<Ticket> getTickets() {
        return tickets;
    }

I try to create thread so that many users can concurrently call the "attemptPuschase" method but that would go against the algorithm of the article that "User are put into a queue and a random queue position then when the sale is started, each user in the queue is put into the holding queue for payment" If I create many threads and the number of users >> numbers of tickets (much greater than) then it may happen that the first user in the queue or second, third, ... those who put first cannot purchase tickets due to the undetermined behaviors of thread. Can anyone help me with a solution.

0

There are 0 best solutions below