2016-03-04 38 views
1

我正在工作在一個簡單的國際象棋A.I. (計算可能的未來轉身,評級他們,選擇最好的一個,+一些技巧,所以你不必計算每一回合)。代碼是用Java編寫的,我使用的是Netbeans。爲了加快計算速度,我使用多線程。代碼的工作原理大致如下:完全相同的代碼(與多線程)不能在2個不同的計算機上工作

  • 主函數首先進行一些計算,然後啓動8個線程。
  • 線程在完成時執行主計算
  • 他們在布爾數組中設置一個布爾值(finished [])true。這個數組在「main class」中(如果你這樣調用它),主函數也是這樣。
  • 在此期間,主函數正在等待並且不斷檢查完成的[] - 數組的每個值是否爲真。如果是這樣,它會繼續它的工作。

現在我有一個奇怪的問題。該代碼完美地在我的電腦上運行,但是當我在我的筆記本電腦上運行EXACT相同的代碼時,主函數在完成[] - 數組的所有值爲真後都不會繼續工作。我已經對代碼做了一些修改,所以我可以用不同數量的線程來嘗試它,但結果總是一樣的。

我完全不知道這裏發生了什麼,真的很感激它,如果你的某個人有任何答案和/或建議!

如果您需要更多信息,只需詢問,我會盡我所能。 :)

(對不起,可能的語法錯誤,英語不是我的母語,但我想我最好的;))

所以我要求出示我在程序中使用一些代碼:

(也許是第一次警告,是的,我仍然在Java中的大菜鳥,這是我第一次用我的線程,所以不要被震撼工作,如果你看到可怕的錯誤我可能做。XD)

主類看起來像這樣:

public class Chess_ai_20 { 

    static boolean finished[] = new boolean[8]; 
    Distributor[] Distributors = new Distributor[8]; 
    ... 

    public static void main(String[] args) { 
     boolean testing=false; 
     ... 
     //some calculations and other stuff 
     ... 
     Distributors[0] = new Distributor(...., "0"); //the String "0" will be the thread name. 
     Distributors[1] = new ... 
     ... 
     Distributors[7] = new Distributor(...., "7"); 

     for (int i = 0; i < 8; i++) { 
      Distributoren[i].start(); 
     } 

     testing=false; 

     while(testing==false){ 
      if(finished[0]==true && finished[1]==true && ... && finished[7]==true){ 
      testing=true; //That's the point where I get stuck I suppose 
      } 
     } 

     System.out.println("I made it!"); 
    } 

    public static void setFinished(int i) { 
     finished[i] = true; 
     System.out.println("finished [" + i + "] = " + finished[i]); 
     System.out.println(Arrays.toString(finished)); //To check how many values already are true 
    } 
} 

然後,我們當然類「分銷商」

public class Distributor extends Thread { 
    Thread t; 
    String threadname; 
    boolean running=false; 
    ... 
    Distributor(......, String s) { 
     threadname=s; 
     ... 
     ... 
    } 

    @Override 
    public void start() { 
     running=true; 
     if (t == null) { 
      t = new Thread(this,threadname); 
      t.start(); 
     } 
    } 

    @Override 
    public void run() { 
     if(running){ 
     ... 
     //Do the main calculations etc. 
     ... 
     //All the Calculations habe been done at this point 
     Chess_ai_20.setFinished(Character.getNumericValue(threadname.charAt(0))); //Set the value of finished[] true in the main class 
     running=false; 
     } 
    } 
} 
+4

您應該發佈代碼。從你的描述來看,這看起來像是一場競賽狀況很可能已經發生了。 – asgs

+1

您應該發佈代碼。我的猜測是對完成[]的訪問沒有正確同步。 –

+0

'volatile boolean []'我假設。調用['thread.join()s'](http://docs.oracle.com/javase/tutorial/essential/concurrency/join.html)將是另一種解決方案。 –

回答

1

正如其他人所說,使用Future將會更簡單,易於理解。下面是一段代碼,演示如何重寫代碼。查看code in action

首先,您編寫了一個Callable來定義您想要執行的任務。

public class MyCallable implements Callable<Boolean> { 

    @Override 
    public Boolean call() { 
     // Do some job and return the result. 
     return Boolean.TRUE; 
    } 
} 

然後,您將此任務提交到Executor。 JDK中有很多Executors。你首先要經過Concurrency Tutorial

ExecutorService executor = Executors.newFixedThreadPool(Runtime 
      .getRuntime().availableProcessors()); 
    List<Callable<Boolean>> callables = new ArrayList<>(); 
    for (int counter = 0; counter < 8; counter++) { 
     callables.add(new MyCallable()); 
    } 

    List<Future<Boolean>> futures = executor.invokeAll(callables); 
    for (Future<Boolean> future : futures) { 
     System.out.println(future.get()); // You'd want to store this into an array or wherever you see fit. 
    } 

    executor.shutdown(); 

記住futures returned by the executor are in the same order as the Callables you submitted (or added)Collection(在這種情況下,ArrayList)。因此,您無需擔心返回索引,ID或甚至是Thread(如果指定了一個)的名稱以映射相應的結果。

+1

非常感謝偉大的教程和對其他文檔的參考!我改變了我的代碼,並通過一個線程池和期貨來牽連你的提議系統。該代碼現在可以在我的筆記本電腦和我的電腦上成功運行! :)祝你有美好的一天,再次感謝! –

相關問題