Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how future get() method works with timeout

Tags:

java

I am a bit confused how Future.get(timeout) works as per the definition it would through an exception after specified timeout time, but its not happening in my test cases.

import java.util.LinkedHashSet;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
 import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

public class CallableExample {

public static class WordLengthCallable implements Callable<String> {
    private String word;
    private long waiting;

    public WordLengthCallable(String word, long waiting) {
        this.word = word;
        this.waiting = waiting;
    }

    public String call() throws InterruptedException {
        Thread.sleep(waiting);
        return word;
    }
}

public static void main(String args[]) throws Exception {
    args = new String[] { "i", "am", "in", "love" };
    long[] waitArr = new long[] { 3000, 3440, 2500, 3000 };
    ExecutorService pool = Executors.newFixedThreadPool(3);
    Set<Future<String>> set = new LinkedHashSet<Future<String>>();
    int i = 0;
    for (String word : args) {
        Callable<String> callable = new WordLengthCallable(word, waitArr[i++]);
        Future<String> future = pool.submit(callable);
        set.add(future);
    }
    String sum = "";
    for (Future<String> future : set) {
        try {
            sum += future.get(2000, TimeUnit.MILLISECONDS) + ", ";
        } catch (Exception e) {
        }
    }
    System.out.print("Result : " + sum);
}
}

output "am, in,"

it behaves differently on changing waiting time in array( timeArr values). when to use get with timeout?

like image 913
RQube Avatar asked Oct 18 '25 12:10

RQube


1 Answers

In your for-loop you wait for the first future to complete. This may take 2000 millis. At this time all the other threads will sleep. Hence, all the values of the other threads are 2000 millis less. Then you wait another 2000 millis and perhaps the future you wait for returns. Hence, two or more threads will succeed.

In each iteration of your loop you donate 2000 millis to the other thread. Only if one future returns successfully, you donate less to the remaining futures. If you would like to observe all futures to fail, due to the 2000 millis timeout, you would have to process them in parallel as well.

If you change some of your code this way:

Set<Callable<String>> tasks = new HashSet<>();
for (String word : args) {
    tasks.add(new WordLengthCallable(word, waitArr[i++]));
}
List<Future<String>> futures = Executors.newFixedThreadPool(3)
        .invokeAll(tasks, 2000, TimeUnit.MILLISECONDS);

you should observe that none of the tasks will succeed, due to the wait times of:

3000, 3440, 2500, 3000

for each Callable created, which are all greater than 2000.

like image 55
Harmlezz Avatar answered Oct 21 '25 00:10

Harmlezz