2017-04-26 106 views
0

我是新来的多线程,并试图创建一个多线程java预订系统。代理商可以预订座位并可选择多家航空公司。这是我的代理类:如何实现同步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是在预约类同步方法是这样的:

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

Howeve r,出于某种原因输出如下所示:

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 

我不知道为什么第一个线程线程0不阻止线程1进入显示器。就像我说的,我对Java多线程是新手,非常感谢一些指导,谢谢。

+3

您正在实例化两个单独的Reservation类,因此两个线程不会竞争。尝试实例化一个预留类并将其提供给两个代理。 – Code4aliving

+1

工作,谢谢@BradBales!尽管在这个例子中,我认为为每个预留创建新的预订实例并使用同步方法创建一个新的ReservationSystem类更有意义,该方法将预订实例作为参数,如@Andy Thomas在他的答案中所建议的。 – sums22

回答

1

同步对象同步对象不能同时运行。

您有两个不同的Reservation对象。他们的同步是彼此独立的。

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

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

Java tutorial on synchronized methods,用加上强调:

首先,它是不可能的同一对象上同步方法交织两个调用。当一个线程正在执行一个对象的同步方法时,所有其他线程调用同一对象的同步方法块(挂起执行),直到第一个线程完成对象。

+0

这使得很多的意义,非常感谢你:) – sums22