我是Java的新手,我写了这个Race计划。我试图运行它,但它在Race和RaceMain类中给出了非法监视器状态异常错误...你能帮忙吗?
public class RaceMain {
public static void main(String args[]) throws InterruptedException{
Pitstop p = new Pitstop();
Race r = new Race();
new Car("Ryan Hunter", r, p);
new Car("Takumo Sato", r, p);
new Car("Scott Dixon", r, p);
new Car("Sebastien Bourdais", r, p);
r.StartRace();
}
}
public class Race {
int rank = 0;
void getToStart() throws InterruptedException{
wait();
}
void StartRace() throws InterruptedException{
Thread.sleep(1000);
notifyAll();
}
synchronized void FinishRace(Car c){
rank = rank +1;
System.out.println("<<<<<<" + c.name + " finished " + geth(rank) + ">>>>>>");
}
String geth(int i){
switch(i % 10){
case 1:
return i + "st";
case 2:
return i + "nd";
case 3:
return i +"rd";
default:
return i + "th";
}
}
}
public class Car implements Runnable{
String name;
Race r;
Pitstop p;
int rand;
int lapsCompleted;
boolean needRep = false;
Car(String n, Race r, Pitstop p){
name = n;
this.r = r;
this.p = p;
}
public void run(){
try{
r.getToStart();
System.out.println(name + " is off and speeding!");
for(int i = 1; i < 10; i++){
if(needRep){
p.repair(name);
needRep = false;
}
runLap();
}
}catch(InterruptedException e){
System.out.println(e);
}
}
void runLap() throws InterruptedException{
rand = (int)(Math.random() % 500) + 1000;
Thread.sleep(rand);
System.out.println(name + " completed his " + geth(lapsCompleted) + " lap");
if(Math.floor(Math.random()*10) == 5){
System.out.println("Oh snap! Looks like " + name + "'s tire has got bursted during the race!");
needRep = true;
}
}
String geth(int i){
switch(i % 10){
case 1:
return i + "st";
case 2:
return i + "nd";
case 3:
return i +"rd";
default:
return i + "th";
}
}
}
public class Pitstop {
synchronized void repair(String n) throws InterruptedException{
int dur = (int) (Math.random() * 1000) % 1000 + 5000;
Thread.sleep(dur);
double sec = dur / 1000;
System.out.println(n + " stopped for " + sec);
}
}
答案 0 :(得分:3)
您有两种方法属于您需要同步的竞赛代码:
void getToStart() throws InterruptedException{ wait(); } void StartRace() throws InterruptedException{ Thread.sleep(1000); notifyAll(); }
这两个方法都调用仅在同步块内部有效的其他方法:
您的方法需要同步:
synchronized void getToStart() throws InterruptedException{
wait();
}
synchronized void StartRace() throws InterruptedException{
Thread.sleep(1000);
notifyAll();
}
答案 1 :(得分:0)
好像你想要运行多个线程,因为Car
实现了Runnable
?
这将是正确的方法:
Pitstop p = new Pitstop();
Race r = new Race();
new Thread(new Car("Ryan Hunter", r, p)).start();
new Thread(new Car("Takumo Sato", r, p)).start();
new Thread(new Car("Scott Dixon", r, p)).start();
new Thread(new Car("Sebastien Bourdais", r, p)).start();
r.StartRace();
现在,就这两种方法而言,我会完全删除它们。首先是因为错误地从错误的线程中调用它们,其次是因为我没有看到它们的目的:
void getToStart() throws InterruptedException{
// remove this
}
void StartRace() throws InterruptedException{
// remove this
}
现在您可以在run方法中添加Thread.yield
,如下所示:
public void run() {
try {
System.out.println(name + " is off and speeding!");
for (int i = 1; i < 10; i++) {
if (needRep) {
p.repair(name);
needRep = false;
}
runLap();
Thread.yield();
}
} catch (InterruptedException e) {
System.out.println(e);
}
结果:
Takumo Sato is off and speeding!
Sebastien Bourdais is off and speeding!
Ryan Hunter is off and speeding!
Scott Dixon is off and speeding!
Ryan Hunter completed his 1st lap
Scott Dixon completed his 1st lap
Sebastien Bourdais completed his 1st lap
Takumo Sato completed his 1st lap
Oh snap! Looks like Ryan Hunter's tire has got bursted during the race!
Scott Dixon completed his 2nd lap
Sebastien Bourdais completed his 2nd lap
Takumo Sato completed his 2nd lap
Scott Dixon completed his 3rd lap
Oh snap! Looks like Scott Dixon's tire has got bursted during the race!
Sebastien Bourdais completed his 3rd lap
Takumo Sato completed his 3rd lap
Oh snap! Looks like Takumo Sato's tire has got bursted during the race!