JAVA: How to stop the execution of a function after a specific time?

3.7k Views Asked by At

I want to implement iterative deepening (incremental tree building). This is the part of my code I will ask about:

        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();

From what I read about invokeAny() with time limit it should end executing its Callable objects as soon as the deadline is reached. It works when I put long sleep instead of my function iterativeDeepening(depthLimit, board). How to make it work with my function? Below I paste the code to this function:

    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);

    }
}

If you know a better way to make it or know how to successfully stop execution of my function please let me know. I tried also a Runnable Interface mentioned in this topic: How to stop execution after a certain time in Java? but it just worked the same.

1

There are 1 best solutions below

4
On

After the timeout is reached, the ExecutorService will try to interrupt all the currently running tasks by calling Thread.interrupt() on them. This will put each of the threads to an interrupted state. sleep() quits when this state is set.

So adding this check:

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

inside your function should do the job.

A tip for you thread termination:

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

That's not a solution because inside a loop there is a function gameTree.buildGameTree(depth, root); which itself sometimes takes longer than the deadline which is crucial.

As far as I know, there is no way to interrupt such function from outside. This function should check it's state from time to time. If it's a loop, consider checking the state on some or all of the iterations.