java - 如何实现Java同步方法

标签 java multithreading runnable synchronized

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

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

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

    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 多线程的新手,非常感谢一些指导,谢谢。

最佳答案

同一个对象上的同步方法不能同时运行。

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

解决此问题的一种方法是创建一个带有同步方法的 ReservationSystem 类来预订座位,并为多个 Reservation 实例创建一个实例。

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

来自Java tutorial on synchronized methods ,并强调:

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.

关于java - 如何实现Java同步方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43644948/

相关文章:

java - 通用数组初始化

Java-异常处理

java - Java 语法中的静态 {} 是什么意思?

java - 将 JDBC Type 3 驱动程序与 Java 1.6 结合使用

java - 通知不同对象中的线程

asp.net - IIS 服务器如何工作(线程)

c# - 类(class)之间的调度员

java - 无法使用 JavaFX 更改可运行对象中的接口(interface)

java - 可运行代码正在循环其操作

java - 如何用另一个 JPanel 替换 JPanel