0

我想實現迭代加深(增量樹構建)。這是我的代碼的一部分,我會問:JAVA:如何在特定時間後停止函數的執行?

 ExecutorService executorService = Executors.newSingleThreadExecutor(); 

     Set<Callable<Integer>> callables = new HashSet<Callable<Integer>>(); 

     callables.add(new Callable<Integer>() { 
      public Integer call() throws Exception { 
       iterativeDeepening(depthLimit, board); 
       return -1; 
      } 
     }); 
     callables.add(new Callable<Integer>() { 
      public Integer call() throws Exception { 
       Thread.sleep(500); 
       return 1; 
      } 
     }); 
     try{ 
      executorService.invokeAny(callables, 1000, TimeUnit.MILLISECONDS); 
     }catch(TimeoutException | InterruptedException ex){ 
      executorService.shutdown(); 
     } 

     executorService.shutdown(); 

從我有時間閱讀invokeAny()限制它應該結束,因爲一旦達到限期執行的可調用對象。它在我長時間睡眠而不是我的函數iterativeDeepening(depthLimit,board)時起作用。如何使它與我的功能一起工作? 下面我的代碼粘貼到該函數:

public void iterativeDeepening(byte depthLimit, byte[] board){ 

    for(byte depth=1;depth<depthLimit;depth++){ 
     GameTree gameTree= new GameTree(); 
     byte[] tempBoard = new byte[14]; 
     for(byte i=0;i<14;i++){ 
      tempBoard[i] = board[i]; 
     } 
     Node <byte[]> root= new Node<byte[]>(tempBoard, player); 
     try { 
      gameTree.buildGameTree(depth, root); 
     } catch (OutOfMemoryError E) { 
      gameTree.eraseGameTree(depth,root); 
      System.gc(); 
     } 

     MiniMax minimax = new MiniMax(player); 
     move= minimax.selectMove(depth, root); 

    } 
} 

如果你知道一個更好的辦法,使之或不知道如何成功地阻止我的函數的執行,請讓我知道。我也嘗試了一下本主題中提到的Runnable接口: How to stop execution after a certain time in Java? 但它的工作原理是一樣的。

+0

如果你希望它是自包含的,你可以在進入循環之前存儲一個System.currentTimeMillis()變量。然後在循環的每次迭代中檢查if(System.currentTimeMillis() - startTime> = maxRunTime)。 – Radiodef

+0

這不是一個解決方案,因爲在循環內部有一個函數gameTree.buildGameTree(深度,根);其本身有時需要比截止日期更重要的時間。 – user2923339

+0

您可以將開始時間作爲參數傳遞。 @AndreyChaschev可能是正確的,你最好的選擇就是檢查中斷。中斷一個線程不一定會過早結束它,而無需自己檢查中斷。 – Radiodef

回答

1

達到超時後,ExecutorService將嘗試通過調用Thread.interrupt()來中斷所有當前正在運行的任務。這將使每個線程處於中斷狀態。當這個狀態被設置時,sleep()退出。

因此增加此項檢查:

if(Thread.currentThread().interrupted()) { 
    return; 
} 

你的函數應該做的工作裏面。

你線程終止尖端:

try{ 
    executorService.invokeAny(callables, 1000, TimeUnit.MILLISECONDS); 
} catch(TimeoutException | InterruptedException ex){ 
    //... ignore 
} finally { 
    executorService.shutdown(); 
    executorService.awaitTermination(); <-- add this line if you want to wait for the computation to end 
} 

UPDATE

這不是一個解決方案,因爲在一個循環內有一個函數gameTree.buildGameTree(深度,根);其本身有時需要比截止日期更重要的時間。

據我所知,沒有辦法從外面打斷這樣的功能。這個函數應該時常檢查它的狀態。如果是循環,請考慮在某些或所有迭代中檢查狀態。

+0

不......不幸的是,它不是一個循環,而是一個非常奇怪的遞歸函數。在開始時(buildGameTree(...)),我添加了startTime作爲參數,如果時間結束,我會在開始時檢查。如果是這樣 - 我返回一個被捕獲的異常並返回結果。奇怪的是,時間限制甚至經常超過2-3次。我試着用nanoTime()和currentTimeMillis()來得到相同的結果。 – user2923339

+0

您可能需要在線程的頂級顯式捕獲異常。 –

+0

爲什麼不直接?由於我開始把時間作爲一個論點,我平息了這兩個功能。捕捉看起來像這樣: 嘗試{gameTree.buildGameTree(深度,根,startTime,timeLimit); \t \t } catch(OutOfMemoryError | Exception e){return move;} – user2923339

相關問題