0

I am new to multithreading and am trying to create a multithreading java booking system. An agent can reserve a seat and has the choice of multiple airlines. This is my Agent class:

public class Agent implements Runnable {
private int id;
private Reservation reservation;

public Agent() {

}

public Agent(Reservation reservation) {
    this.reservation = reservation;

}

@Override
public void run() {
    try {
        reservation.reserveSeat();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

}

The reserveSeat is a synchronised method in the the Reservation class and is as such:

public synchronized boolean reserveSeat() throws InterruptedException {
    System.out.println(Thread.currentThread().getName() + " entered.");

    List<Seat> availableSeats = airline.getAvailableSeats();

    // if there are no available seats
    while (availableSeats.isEmpty())
        wait();

    Seat seat;
    // repeat this until an available seat is chosen
    try {
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));

        do {
            System.out.println("Please choose from the following available seats: ");
            for (Seat s : availableSeats) {
                System.out.print(s.getNumber() + " ");
            }
            System.out.println();

            String input = reader.readLine();
            int seatNum = Integer.parseInt(input);
            seat = airline.getSeatObjectWithNumber(seatNum);
        } while (!availableSeats.contains(seat));

        this.seat = seat;

        // enter passenger details
        System.out.println("Please enter the passenger's name. ");
        // create passenger instance
        String name = reader.readLine();
        this.passenger = new Passenger(name);

        // change seat status to reserved
        seat.setReserved(true);

        // add this reservation to the list of reservations the airline has
        airline.getReservations().add(this);

        notifyAll();

        System.out.println(Thread.currentThread().getName() + " leaving.");
        System.out.println("----------------------------------------------");
    } catch (IOException e) {
        e.printStackTrace();
    }

    return true;
}

I am then trying to test my code in my main method by creating two agent instances that each try to make a reservation:

    Reservation reservation1 = new Reservation(airline1);
    Agent agent1 = new Agent(reservation1);
    new Thread(agent1).start();

    Reservation reservation2 = new Reservation(airline2);
    Agent agent2 = new Agent(reservation2);
    new Thread(agent2).start();

However, for some reason the output looks like this:

Thread-0 entered.
Thread-1 entered.
Please choose from the following available seats: 
1 2 3 
Please choose from the following available seats: 
1 2 3 

I am not sure why the first thread Thread-0 is not blocking Thread-1 from entering the monitor. Like I said I am new to multithreading in Java and would really appreciate some guidance, thanks.

Andy Thomas
  • 84,978
  • 11
  • 107
  • 151
sums22
  • 1,793
  • 3
  • 13
  • 25
  • 3
    You're instantiating two separate Reservation classes, so the two threads aren't competing. Try instantiating one reservation class and give it to both agents. – Code4aliving Apr 26 '17 at 21:42
  • 1
    That works, thanks @BradBales! Although within this example I think it makes more sense to create new Reservation instances for each reservation and and create a new ReservationSystem class with a synchronised method that takes a reservation instance as a parametre as @Andy Thomas suggested in his answer. – sums22 Apr 27 '17 at 10:43

1 Answers1

1

Synchronized methods on the same object cannot be run at the same time.

You have two different Reservation objects. Their synchronization is independent of each other.

One way to fix this would be to create a ReservationSystem class with a synchronized method to reserve a seat -- and create one instance of it for multiple Reservation instances.

public class ReservationSystem {
   public synchronized boolean reserveSeat( Reservation reservation ) {
      ...
   }
}

From the Java tutorial on synchronized methods, with added emphasis:

First, it is not possible for two invocations of synchronized methods on the same object to interleave. When one thread is executing a synchronized method for an object, all other threads that invoke synchronized methods for the same object block (suspend execution) until the first thread is done with the object.

Andy Thomas
  • 84,978
  • 11
  • 107
  • 151