我很难理解多线程。不幸的是,这是我需要提交的作业之一才能通过该课程。
这是关于火车的: - 火车等待乘客线程派遣一些乘客,直到达到容量。
然后火车去兜风。在此期间,没有乘客登上火车。
下一步是取消操作,这是Passenger线程调用的过程。
一旦发生这种情况,周期将与其他乘客一起继续。
我在unboarding部分遇到了麻烦,有时候我会得到一个超出界限的异常。
这是错误:
乘客3登上了火车
乘客0已登上火车
乘客1登上了火车
乘客12登上了火车
乘客13登上了火车
火车满车
座位:0乘客:3
座位:1名乘客:0人
座位:2名乘客:1人
座位:3名乘客:12人
座位:4名乘客:13人
骑行开始
骑行结束
乘客3想下车。座位:0
乘客:火车下车3
乘客离开:0
乘客离开:1
线程“Thread-16”中的异常java.lang.ArrayIndexOutOfBoundsException:-1
at java.util.ArrayList.elementData(Unknown Source)
at java.util.ArrayList.remove(Unknown Source)
在parque.Train.unboardTrain(Train.java:104)
在parque.Passenger.run(Passenger.java:23)
乘客离开:12
乘客离开:13
乘客15想要下车。座位:-1 //没有乘客ID 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 :(得分:0)
问题是有些乘客在没有列车的情况下试图挂机。在&#39; boardTrain&#39;中查看您的代码并包含以下更改以更好地了解您的问题(当乘客无法进入火车时,请参阅新消息):
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进入火车的任何消息)。
接下来会发生什么?登上火车后,乘客试图取消火车:
t.boardTrain(this.id);
t.unboardTrain(this.id);
但是,如果没有进入火车的乘客试图登机,会发生什么?您将收到如下消息:
乘客15想要下车。座位:-1
然后代码继续执行以下行:
passengers.remove(passengers.indexOf(pasajeroId));
并抛出异常,因为&#39; passengers.indexOf(pasajeroId)&#39;值为-1,正如您在文档中看到的那样,-1不是有效的索引:http://docs.oracle.com/javase/7/docs/api/java/util/ArrayList.html#remove(int)
尝试使用&#39; boardTrain&#39;返回一个布尔值。方法,只有在乘客上火车的情况下才能登机。
我希望这会有所帮助;)。 Suerte。
答案 1 :(得分: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