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

相关问题