未来get()方法如何使用超时

时间:2014-04-04 13:17:59

标签: java

我有点困惑,Future.get(超时)如何按照定义超时时间之后的异常定义,但在我的测试用例中没有发生。

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

输出“am,in,”

它在更改数组中的等待时间(timeArr值)时表现不同。何时使用get with timeout?

2 个答案:

答案 0 :(得分:2)

在你的for循环中,你等待第一个未来完成。这可能需要2000毫升。此时所有其他线程都将睡眠。因此,其他线程的所有值都小于2000毫。然后你再等2000毫升,或许未来等待回报。因此,两个或多个线程将成功。

在循环的每次迭代中,您将2000毫秒捐赠给另一个线程。只有当一个未来成功返回时,您才会向剩余的期货捐赠更少。如果您希望观察到所有期货失败,由于2000毫秒超时,您还必须并行处理它们。

如果您以这种方式更改某些代码:

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

由于等待时间:

,您应该注意到任何任务都不会成功
3000, 3440, 2500, 3000

创建的每个Callable,都大于2000。

答案 1 :(得分:1)

编辑:感谢@RQube警告我线程的执行顺序为3.线程将在1.之前完成.4。线程将在3.完成后开始而不是1.

首先,你的线程池大小为3.这意味着你的4. Future将等待3.完成。

让我们假设除了线程等待之外没有耗时的工作。执行将是这样的:

  1. 未来 - 3000毫秒等待时间 - 这会抛出超时异常但会继续运行,因为您没有在超时时终止它。所以你的4. Future还在等待一个线程完成。 总执行时间:2000ms

  2. 未来 - 1440毫秒等待,因为你已经等待2000毫秒 - 这将返回你在输出“am”中看到的。同样在2500ms标记3.未来将被执行4.未来将在2500ms标记处开始。 总执行时间:3440ms

  3. 未来 - 没有等待时间,因为我们已经等待3440ms,这将立即返回。 总执行时间:3440ms。

  4. 未来 - 2060毫秒等待时间结束,因为这已经开始于2500毫秒大关,并且在启动后940毫秒已经过去。这将在2000ms(等待2940ms)之后超时

  5. 正如你只能看到2.和3.当你调用get()但实际上所有这些都被执行时,期货将会返回。

    对不起格式错误和任何错别字,因为我在手机上写作。