如何实现同步Java方法

时间:2017-04-26 21:39:08

标签: java multithreading runnable synchronized

我是多线程的新手,我正在尝试创建一个多线程的Java预订系统。代理商可以预订座位并可选择多家航空公司。这是我的Agent类:

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();
    }
}

}

reserveSeat是Reservation类中的同步方法,如下所示:

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;
}

然后我尝试通过创建两个代理实例来尝试在我的main方法中测试我的代码,每个代理实例都尝试进行预订:

    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();

但是,出于某种原因,输出看起来像这样:

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 

我不确定为什么第一个线程Thread-0没有阻止Thread-1进入监视器。就像我说我是Java新手,我非常感谢一些指导,谢谢。

1 个答案:

答案 0 :(得分:1)

同一对象上的同步方法无法同时运行。

您有两个不同的Reservation对象。它们的同步是相互独立的。

解决此问题的一种方法是使用同步方法创建一个ReservationSystem类来预留座位 - 并为多个预留实例创建一个实例。

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

来自Java tutorial on synchronized methods,更加强调:

  

首先,两个同步方法的调用不可能在同一个对象上进行交错。当一个线程正在为对象执行同步方法时,所有其他线程都会调用同一对象的同步方法阻塞(暂停执行),直到第一个线程完成对象为止。