2015-08-12 6 views
0

Мне сложно понять многопоточность. К сожалению, это одно из заданий, которые мне нужно подать, чтобы пройти курс.Multithread. Явные блокировки и условия

Речь идет о поезде: -Поезд ждет пассажирской темы, чтобы отправить пассажиров, пока не будет достигнута пропускная способность.

  • Затем поезд отправляется в путь. В течение этого периода пассажиры не могут сесть на поезд.

  • Следующий шаг - unboarding, это процедура, называемая потоком пассажира.

  • Как только это произойдет, цикл продолжается с остальными пассажирами.

У меня возникают проблемы с нерабочей частью, иногда я получаю исключение для массива за пределами.

Вот ошибка:

Пассажир 3 уже сел на поезд
Пассажир 0 имеет сел на поезд
Пассажир 1 имеет сел на поезд
Пассажир 12 имеет сел на поезд
Пассажир 13 имеет сел на поезд
ПОЕЗД ПОЛНЫЙ
СИДЕНЬЯ: 0 Пассажир: 3
сиденья: 1 Пассажир: 0
сиденья: 2 Passenge г: 1
СИДЕНЬЯ: 3 Passenger: 12
СИДЕНЬЯ: 4 Passenger: 13
RIDE НАЧИНАЕТСЯ
RIDE ЗАКАНЧИВАЕТСЯ
Пассажир 3 хочет сойти с поезда. Сиденье: 0
Пассажир: 3 с поезда
пассажира (ов) слева направо: 0
Пассажир (ы) слева направо: 1
Исключение в потоке java.lang.ArrayIndexOutOfBoundsException "Автор-16": -1
в java.util.ArrayList.elementData (Unknown Source)
в java.util.ArrayList.remove (Unknown Source)
в parque.Train.unboardTrain (Train.java:104)
в parque.Passenger.run (Passenger.java:23)
Пассажир (и): 12
Пассажир (и): 13
Пассажир 15 хочет сойти с поезда. SEAT: -1 // Нет пассажира 15, а?

Я хотел бы знать, как я могу избежать этого исключения? Я подумал, что, возможно, может быть реализован другой замок отдельно от замка поезда, который будет отвечать за двери, или, может быть, это должно быть реализовано как условие?, Помогите, пожалуйста,

Вот код:

public class Train extends Thread { 
    private int id; 
    private int capacity; 
    private ArrayList<Integer> passengers; 
    private Lock l = new ReentrantLock(); 
    private Condition trainFull = l.newCondition(); 
    private Condition boardTrain = l.newCondition(); 
    private Condition UnboardTrain = l.newCondition(); 
    private boolean canBoard = true; 
    private boolean canUnboard = false; 



//se definen los constructores 
    public Train(int id, int capacity) { 
     this.id = id; 
     this.capacity = capacity; 
     this.passengers = new ArrayList<Integer>(capacity); 

    }//fin constructor 
    public Train(int id) { 
     this.id = id; 
     this.capacity = 5; 
     passengers = new ArrayList<Integer>(capacity); 

    }//fin constructor 

    public void boardTrain(int passengerId) { 
     l.lock(); 

     try{ 
      while(!canBoard) 
       boardTrain.await(); 
       if (passengers.size() == capacity) { 
        canBoard = false; 
        trainFull.signal(); 
       } else { 
        passengers.add(passengerId); 
        System.out.println("Passenger " + passengerId +" has boarded the train"); 
       }//if 

     } catch (InterruptedException e) { 
      e.printStackTrace(); 
      System.out.println("Exception at boarding"); 
     }finally{ 
      l.unlock(); 
     }//try 


    }//fin subir 

    public void waitsFullTrain() {  //waits until n (capacity) passengers board the train 
     l.lock(); 

     try{ 
      trainFull.await(); 

      System.out.println("TRAIN FULL"); 
      for(int i = 0; i< passengers.size(); i++){ 
       System.out.println("   SEAT: " + i + " Passenger: " + passengers.get(i)); 
      }//for 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     }finally{ 
      l.unlock(); 
     }//try 


    }//fin esperaLleno 

    public void goForRide() throws InterruptedException{ 

     l.lock(); 
     try{ 
      System.out.println("RIDE STARTS"); 
      Thread.sleep(2000); 
      System.out.println("RIDE ENDS"); 
      canUnboard = true; 
      UnboardTrain.signalAll();  

     }finally{ 
      l.unlock(); 
     }  

    }//fin darVuelta 


    public void unboardTrain(int pasajeroId) { 
     l.lock(); 

     try{ 
      while(!canUnboard) 
       UnboardTrain.await(); 
      //System.out.println("Bajando.."); 
      if(passengers.size() >0){ 
       System.out.println("Passenger "+ pasajeroId + " wants to get off the train. SEAT: "+passengers.indexOf(pasajeroId)); 
       passengers.remove(passengers.indexOf(pasajeroId)); 
       System.out.println(" Passenger: " + pasajeroId + " off the train"); 

       for (int i = 0; i<passengers.size();i++){ 
        System.out.println("   Passenger(s) left: "+passengers.get(i)); 
       } 
      }else{ 
       System.out.println(); 
       canUnboard = false; 
       canBoard = true; 
       boardTrain.signalAll();   
      }//if 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
      System.out.println("Exception at unboarding"); 
     }finally{ 
      l.unlock(); 
     }//try 


    }//fin bajar 



    public int id() { 
     return id; 
    }//fin id 

    @Override 
    public void run() { 
     while(true){ 
      this.waitsFullTrain(); 
      try { 
       this.goForRide(); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
     }//fin while  

    }//fin run 


}//fin clase 


public class Passenger extends Thread{ 

    private int id; 
    private Train t; 

    public Passenger(int id, Train t) { 
     this.id = id; 
     this.t = t; 
    } 

    @Override 
    public void run() { 

     t.boardTrain(this.id); 
     t.unboardTrain(this.id); 

    }//run 
}//Passenger 


public class Main { 

    public static void main(String[] args) { 

     Train t = new Train(1); 
     Passenger[] p = new Passenger[20]; 

     for (int i = 0; i < p.length; i++) { 
      p[i]= new Passenger(i, t); 
     }//for 
     t.start(); 

     for (int i = 0; i < p.length; i++) { 
      p[i].start(); 
     }//for 

     try { 
      t.join(); 
     } catch (InterruptedException e1) { 
      e1.printStackTrace(); 
     } 
     for (int i = 0; i < p.length; i++) { 
      try { 
       p[i].join(); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
     }//for 
    }//main 
}//clase 
+0

Пожалуйста, разместите stacktrace. –

+0

Модель выглядит немного неправильно в этом дизайне для меня. Подумайте о реальном мире ... Пассажиры не могут встать или выйти из поезда, когда двери закрыты или поезд не находится на станции (это должны быть ваши замки). Когда двери открыты, unboard(), board() ... Когда происходит тайм-аут, закрываются двери и поезд. – Dave

+0

Вы забыли задать вопрос! Очень важно, чтобы вы задали конкретный конкретный вопрос. Вот почему кнопка, которую вы нажали, помечена как «Ask Question». –

ответ

0

Проблемы есть некоторые пассажиры пытаются unboard поезда, когда они на самом деле не в этом. Посмотрите на свой код в «boardTrain» и включают в себя следующие изменения для лучшего понимания вашей проблемы (см новое сообщение, когда пассажир не смог попасть в поезде):

if (passengers.size() == capacity) { 
    System.out.println("Passenger " + passengerId + " CANNOT board the train => TRAIN FULL"); 
    canBoard = false; 
    trainFull.signal(); 
} else { 
    passengers.add(passengerId); 
    System.out.println("Passenger " + passengerId +" has boarded the train"); 
} 

Теперь выполнить ваш код несколько раз. Когда вы снова получите ошибку, вы увидите, какой пассажир не попал в поезд (вы также можете увидеть это в своем следе, потому что нет никакого сообщения о том, что пассажир 15 попадает в поезд).

Что будет дальше? После посадки на поезд, пассажир пытается unboard его:

t.boardTrain(this.id); 
t.unboardTrain(this.id); 

но что произойдет, если пассажир, который не попал в поезд пытается unboard? Вы получите ваше сообщение как:

Passenger 15 wants to get off the train. SEAT: -1

, а затем код идет и выполняет следующую строку:

passengers.remove(passengers.indexOf(pasajeroId)); 

и исключение, потому что «passengers.indexOf (pasajeroId)» значение - 1, и, как вы можете прочитать в документации, -1 недействительный индекс: http://docs.oracle.com/javase/7/docs/api/java/util/ArrayList.html#remove(int)

Попытайтесь возвратить логическое значение с помощью метода 'boardTrain' и только на борту, если пассажир отправится в поезд.

Надеюсь, это поможет;). Суерте.

+0

Ошибка, на которую вы указали, правильно, но решение должно быть таким, чтобы пассажир должен был подождать, пока он не сможет фактически сесть на поезд. – xeed

+0

BitExodus благодарит меня за это, я не думал о тех пассажирах, которые не могли сесть на поезд. К сожалению, нельзя изменить тип возврата, но попытается выяснить, каким образом только те, кто сели на поезд, могут без борта, gracias! –

+0

@xeed, что является вариантом, я полагаю, это зависит от определения проблемы. Пассажир мог подождать, чтобы сесть в поезд или покинуть станцию, кто знает. Справедливо. – BitExodus

0

Итак, после того, как играть с этой вещью, вот правильное применение в случае, если кто может понадобиться:

В конце концов, трюк проверки, если поезд заполнен сразу после того, пассажир сел. Я разрешал следующему пассажиру использовать метод boardTrain, а затем проверял мощность, если был полон, отклонил этот пассажир, но этот пассажир «потерялся», поэтому у меня была небольшая проблема в методе unboard и ArrayIndexOutOfBoundsException: -1.

public class Train extends Thread { 
    private int id; 
    private int capacity; 
    private ArrayList<Integer> passengers; 
    private Lock l = new ReentrantLock(); 
    private Condition trainFull = l.newCondition(); 
    private Condition boardTrain = l.newCondition(); 
    private Condition unboardTrain = l.newCondition(); 
    private boolean canBoard = true; 
    private boolean canUnboard = false; 



//se definen los constructores 
    public Train(int id, int capacity) { 
     this.id = id; 
     this.capacity = capacity; 
     this.passengers = new ArrayList<Integer>(capacity); 

    }//fin constructor 
    public Train(int id) { 
     this.id = id; 
     this.capacity = 5; 
     passengers = new ArrayList<Integer>(capacity); 

    }//fin constructor 

    public void boardTrain(int passengerId) { 
     l.lock(); 

     try{ 
      while(!canBoard) 
       boardTrain.await(); 
      passengers.add(passengerId); 
      System.out.println("Passenger: " + passengerId +" has boarded the train"); 

      if (passengers.size() == capacity) { //<------this here did the trick! 
       canBoard = false; 
       trainFull.signalAll(); 
      } 


     } catch (InterruptedException e) { 
      e.printStackTrace(); 
      System.out.println("Exception at boarding"); 
     }finally{ 
      l.unlock(); 
     }//try 


    }//fin subir 

    public void waitsFullTrain() {  //waits until n (capacity) passengers board the train 
     l.lock(); 

     try{ 
      trainFull.await(); 
         System.out.println("TRAIN FULL"); 
      for(int i = 0; i< passengers.size(); i++){ 
       System.out.println("   SEAT: " + i + " Passenger: " + passengers.get(i)); 
      }//for 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     }finally{ 
      l.unlock(); 
     }//try 


    }//fin esperaLleno 

    public void goForRide() throws InterruptedException{ 

     l.lock(); 
     try{ 
      System.out.println("RIDE STARTS"); 
      Thread.sleep(2000); 
      System.out.println("RIDE ENDS"); 
      canUnboard = true; 
      unboardTrain.signal();  

     }finally{ 
      l.unlock(); 
     }  

    }//fin darVuelta 


    public void unboardTrain(int pasajeroId) { 
     l.lock(); 

     try{ 
      while(!canUnboard) 
       unboardTrain.await(); 
      //System.out.println("Bajando.."); 

      if(passengers.size() >0){ 
       if(passengers.indexOf(pasajeroId) > -1){ 
        System.out.println("Passenger "+ pasajeroId + " wants to get off the train. SEAT: "+passengers.indexOf(pasajeroId)); 
        passengers.remove(passengers.indexOf(pasajeroId)); 
        System.out.println(" Passenger: " + pasajeroId + " off the train"); 
        if(passengers.size() ==0){ 
         System.out.println(); 
         canUnboard = false; 
         canBoard = true; 
         boardTrain.signalAll();       
        }else{ 
         unboardTrain.signal(); 
         System.out.print("  Remaining passengers: "); 
         for (int i = 0; i<passengers.size();i++){ 
          System.out.print(" "+passengers.get(i)); 
         }//for 
        } 


       }else{ 
        unboardTrain.signal(); 
       }//if 
      }else{ 
       System.out.println(); 
       canUnboard = false; 
       canBoard = true; 
       boardTrain.signalAll();   
      }//if 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
      System.out.println("Exception at unboarding"); 
     }finally{ 
      l.unlock(); 
     }//try 


    }//fin bajar 



    public int id() { 
     return id; 
    }//fin id 


    public void run() { 
     while(true){ 
      this.waitsFullTrain(); 
      try { 
       this.goForRide(); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
     }//fin while  

    }//fin run 


}//fin clase