Search code examples
javamultithreadingtimeoutthreadpoolexecutorservice

ExecutorService using invokeAll and timeout on callables thread not got terminated after timeout exception


i try to set a timeout on the thread and expect that the executor to throw exception and prevent the thread form running that it terminating it but this not the case the timeout working find but the thread do complete to execute. how do i terminate the thread if it pass the timeout ? this is my test code :

class ArithmeticBB implements ArithmeticManagerCallable.ArithmeticAction {
    @Override
    public String arithmetic(String n) {
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        String ss  = n+" 2" + " ,Thread ID:" +Thread.currentThread().getId();
        return ss;
    }
}
public class ArithmeticManagerCallable {
    ExecutorService executor = null;
    private List<String> integerList = null;
    private List<String> myResult= Collections.synchronizedList(new ArrayList<>());
    private int threadTimeOutInSec = 180;

    public ArithmeticManagerCallable(List<String> dataFromUser, int poolSize, int threadTimeOutInSec) {
        this.integerList =  dataFromUser;
        executor = Executors.newFixedThreadPool(poolSize);
        this.threadTimeOutInSec = threadTimeOutInSec;
    }
    private void exec(ArithmeticAction arithmeticAction) {
        List<String> tempList = new ArrayList<>();
        for(Iterator<String> iterator = integerList.listIterator(); iterator.hasNext();) {
            tempList.add(arithmeticAction.arithmetic(iterator.next()));
        }
        resultArray.addAll(tempList);
    }
    public List<String> invokerActions(List<ArithmeticAction> actions) throws
            InterruptedException {

        Set<Callable<String>> callables = new HashSet<>();
        for (final ArithmeticAction ac : actions) {
            callables.add(new Callable<String>() {
                public String call() throws Exception{
                    exec(ac);
                    return "done";
                }
            });
        }
        List<Future<String>> futures = executor.invokeAll(callables, this.threadTimeOutInSec, TimeUnit.SECONDS);
        executor.shutdown();
        while (!executor.isTerminated()) {
        }
        return myResult;
    }
    public interface ArithmeticAction {
        String arithmetic(String n);
    }

    public static void main(String[] args) {
        List<ArithmeticManagerCallable.ArithmeticAction> actions = new ArrayList();
        actions.add(new ArithmeticBB());
        List<String> intData = new ArrayList<>();
        intData.add("1");

        ArithmeticManagerCallable arithmeticManagerCallable = new ArithmeticManagerCallable(intData,20,4);

        try {
            List<String> result = arithmeticManagerCallable.invokerActions(actions);
            System.out.println("***********************************************");
            for(String i : result) {
                System.out.println(i);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

Solution

  • Your Thread does not complete it's execution after it exceeds the timeout.

    For reference have a look at this example:

    ExecutorService executorService = Executors.newFixedThreadPool(20);
    
    List<Callable<String>> callableList = new ArrayList<>();
    for (int i = 0; i < 10; i++) {
        final int identifier = i;
        callableList.add(()-> {
            try {
                Thread.sleep(1000 * identifier);
            } catch (InterruptedException e) {
                System.out.println("I'm " + identifier + " and my sleep was interrupted.");
            }
            return identifier + " Hello World";
        });
    }
    
    try {
        List<Future<String>> futureList = executorService.invokeAll(callableList, 5, TimeUnit.SECONDS);
    
        for (Future<String> result : futureList) {
            System.out.println(result.get());
        }
    } catch (InterruptedException | ExecutionException e) {
        System.out.println("Something went wrong while executing. This may help: " + e.getMessage());
    } catch (CancellationException e) {
        System.out.println("Not all Futures could be received.");
    } finally {
        executorService.shutdown();
    }