1

我有一个类,它代表赛车和它的内部,我有一个方法女巫打印到控制台,每当一辆车通过1000 int检查点。Java多线程赛车模拟问题

里面的运行覆盖我称这种方法,它suppoused为我创建的每辆车运行不同,但我想我有什么问题,因为结果每次都会改变(它需要保持不变,因为有些汽车更快,所以我不认为汽车在不同的线程中移动)。

public class RacingCar extends Thread{ 
private String model; 
private int speed; 
public RacingCar(){} 
public RacingCar(String model, int speed){ 
    this.start(); 
    this.model = model; 
    this.speed = speed; 
} 
public void go(){ 
    int trackLength=5000; 
    int checkPointPassed=0; 
    for(int i=0;i<trackLength;i+=speed){ 
     if(checkPointPassed*1000<i){ 
      checkPointPassed++; 
      System.out.println(this.model+" has passed the "+checkPointPassed+"th check point"); 
     } 
    } 
} 
@Override 
public void run() { 
    go(); 
    try { 
     Thread.sleep(10); 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
    } 
}} 

测试仪(主):

public class Tester { 
public static void main(String[] args) { 
    new RacingCar("Honda", 6); 
    new RacingCar("Lamborghini", 100); 
    new RacingCar("McLaren", 8); 
}} 
+0

你有什么样的顺序线程将执行没有保证。你在做什么是创建三个线程,让他们每个循环,直到它打印前达到1000。之后,睡10ms后退出。你可能打算在开始线程之前设置速度,以及在循环内睡觉(但即使如此,你也不会严格保证打印线的顺序......)。 – folkol

+0

尽管可能与原始问题无关,但是您是否确定该命令:'start(); this.model =模型; this.speed =速度;'?行动后初始化? –

+0

每个模拟对象使用一个线程_seriously_限制了您的模拟的可扩展性,它可能也会使您的模拟更加复杂。如果您试图实时模拟某些内容(例如,显示在窗口中),那么您最好使用提交给'ScheduledThreadPoolExecutor'或某种GUI框架计时器的任务来执行您的时间 - 敏感的计算。 –

回答

1

您应该在循环内移动睡眠,并在开始线程之前完全创建RacingCars。

public class RacingCar extends Thread { 
    private String model; 
    private int speed; 

    public RacingCar(String model, int speed) { 
     this.model = model; 
     this.speed = speed; 
    } 

    @Override 
    public void run() { 
     try { 
      go(); 
     } catch(InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } 

    private void go() throws InterruptedException { 
     int trackLength = 5000; 
     int checkPointPassed = 0; 
     for(int i = 0; i < trackLength; i += speed) { 
      if(checkPointPassed * 1000 < i) { 
       checkPointPassed++; 
       System.out.println(this.model + " has passed the " + checkPointPassed + "th check point"); 
      } 
      Thread.sleep(10); 
     } 
    } 
} 

public class Tester { 
    public static void main(String[] args) { 
     RacingCar honda = new RacingCar("Honda", 6); 
     RacingCar lamborghini = new RacingCar("Lamborghini", 100); 
     RacingCar mcLaren = new RacingCar("McLaren", 8); 

     honda.start(); 
     lamborghini.start(); 
     mcLaren.start(); 
    } 
} 

(记住,即使你做到这一点,你必须在命令线程调度运行没有严格的保证。)

+0

你可以把'try'放到'run'的主体中,并让'run'方法返回'InterruptedException' 。看到这样的代码很痛苦,尽管它本来就是这样的。 –

+0

我不想放松中断的线程(相反,我不在乎这个教育的例子) - 我只是想把循环的本质传达给Arie Pinto!:) – folkol

+0

好多了,谢谢 –

0

那么,在这里:

public RacingCar(String model, int speed){ 
    this.start(); 
    this.model = model; 
    this.speed = speed; 
} 
你使用 this.start()完全创建对象前

,这是不好的。 第二件事,你已经在线程运行后分配参数(意味着非确定性行为)。

一般而言,您应该创建对象并在构造函数之外运行它。

+0

等一下,第二个说法是正确的,但是关于“在完全创建对象之前使用它”是什么?当所有的超级构造函数和隐式初始化都完成时,该对象被创建,它不会被传递给构造函数的参数完全初始化,但这可能是有意的(尽管是错误的)。 –

+0

一旦所有构造函数完成,该对象就会完全构造。否则,行为是不确定的。 http://www.javapractices.com/topic/TopicAction.do?Id=254 –

+0

你的意思是说他在对象完全构建之前调用'start'。然后我会同意。但是在构造函数中使用'this'本身并不是一个问题,例如'this.model = model'不会导致任何未定义的行为。这就是我的意思。 –