为什么我的threadExecutor会调用两次相同的回调?

时间:2014-12-28 13:12:21

标签: java multithreading callable executor

我有这段代码:

public <T> T executeCodeBlockWithTimeLimit(String criticalBlockTimeOutMilli, Callable<T> callable) throws
        Exception {
    ExecutorService service = Executors.newSingleThreadExecutor();
    Future<T> future = service.submit(callable);

    startStopWatch();
    T result;

    if (criticalBlockTimeOutMilli != null) {
        result = future.get(Long.parseLong(criticalBlockTimeOutMilli), TimeUnit.MILLISECONDS);
    } else {
        result = callable.call();
    }
    long timeElapsed = stopStopWatch();
    e2eResult.runTime = timeElapsed;
    service.shutdown();
    return result;
}

并在外部方法中:

    Callable<Void> callable = new
            Callable<Void>() {
                @Override
                public Void call() throws
                        Exception {

                    System.out.println("22222");

                    return null;
                }
            };
    timerUtils.executeCodeBlockWithTimeLimit(criticalBlockTimeOutMilli, callable);

我看到控制台打印

22222
22222

为什么这两次被召唤?

5 个答案:

答案 0 :(得分:2)

当您使用submit方法从执行程序获取 Future 时,会调用 Callable 对象方法并存储结果。在您的代码中,首先获得 Future ,然后如果变量criticalBlockTimeOutMillinull,则在Callable对象上调用call()方法。这意味着执行两次 Callable 对象。

您应该使用get()方法,因为此方法使用 Future 对象中已经收集的结果(请参阅Future#get() method)。

答案 1 :(得分:1)

if (criticalBlockTimeOutMilli != null) {
    result = future.get(Long.parseLong(criticalBlockTimeOutMilli), TimeUnit.MILLISECONDS);
} else {
    result = future.get();
}

答案 2 :(得分:0)

也许ExecutorService对你来说不清楚,这里是javadoc供参考:http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ExecutorService.html#submit(java.util.concurrent.Callable)

当您致电submit(Callable)时,执行人服务将为您调用您的可调用对象。你也没有必要调用它。

答案 3 :(得分:0)

如果criticalBlockTimeOutMilli为null,那么执行程序将调用一次callable,并且

result = callable.call();

将再次调用它。

(?)

答案 4 :(得分:0)

假设criticalBlockTimeOutMilli设置为null,则两次调用call方法。一个通过执行者服务提交方法如下:

Future<T> future = service.submit(callable);

然后你通过调用方法调用它,如下所示:

result = callable.call();