2017-04-26 56 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