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'不會導致任何未定義的行爲。這就是我的意思。 –