我正在学习Callables,并决定制作一个非常简单的程序。问题是,当我调用getFutureTask((时,线程被阻塞;线程状态:TIMED_WAITING(在对象监视器上(
你能告诉我为什么会这样吗?当我在futureTask.get((之前写futureTask.run((时,为什么我的程序能工作;我确实理解get((方法等待并返回结果。但无法理解run((方法的作用。我非常感谢你的回答!
public static void main(String[] args) throws ExecutionException, InterruptedException, TimeoutException {
FutureTask futureTask = getFutureTask(1);
System.out.println(futureTask.get());
}
public static FutureTask<Integer> getFutureTask(Integer i) {
return new FutureTask<Integer>(() -> i*45);
}
run
与get
run
是实际启动任务执行的方法。它应该在不同的线程中调用,例如由ExecutorService
调用。
get
不会触发执行,它只是等待任务完成,即run
完成。这显然意味着您在某个线程之前或从另一个线程调用run
。
ExecutorService
和CompletableFuture
CCD_ 10实际上不应该由用户直接使用。它更多的是在窗帘后面使用的类的类型,以便实现一个很好的异步-API。更具体地说,它是Future
的基本实现,例如ExecutorService
在使用它生成任务时返回的
相反,您应该查看ExecutorService
ExecutorService service = Executors.newCachedThreadPool();
...
Future<Integer> task = service.submit(() -> i * 45);
...
Integer result = task.get();
和CompletableFuture
CompletableFuture<Integer> task = CompletableFuture.supplyAsync(() -> i * 45);
...
Integer result = task.get();
以获得一个易于使用的接口来生成异步任务。
CompletableFuture
的优点是,您还可以设置一个操作管道,一旦上一个操作完成,这些操作都将异步执行。例如:
CompletableFuture<Void> task = CompletableFuture.supplyAsync(Foo::readSomeFile)
.thenApplyAsync(Foo::validateData)
.thenApplyAsync(Foo::compressData)
.thenAcceptAsync(Foo::uploadData);
来自FutureTask
:的API
get((-如果需要,等待计算完成,然后检索其结果。
run((-将此Future设置为其计算结果,除非已取消。
因此,run()
将实际运行FutureTask,并最终得出计算结果。另一方面,如果计算完成,get()
会给出结果但它不启动计算,也不调用run()
本身。
另请参阅@Zabuzard的评论:
run是实际开始执行任务的方法。是的应该在不同的线程中调用,例如由ExecutiorService。get不会触发执行,它只是等待任务完成了,这发生在run((的末尾。FutureTask不是实际上应该由用户直接使用。相反,你应该查看ExecutorService和CompletableFuture以获得一个不错的界面以生成异步任务。
您的函数() -> i*45
只是一个可调用函数。除非您真正开始执行,否则它不会真正执行。这正是run()
的作用。
所以,除非您没有明确地启动线程,否则不会调用FutureTask。CCD_ 22被设计为等待线程完成。因此,通常情况下,您开始一项任务(使用run()
(,做一些其他事情,然后使用get()
得到结果,或者如果任务花费的时间比预期的要长,则在那里等待。
你可以检查一下,例如运行一些System.out:
public static FutureTask<Integer> getFutureTask(Integer i) {
return new FutureTask<Integer>(() -> {
System.out.println("Task started");
return i * 45;
});
}
你不会看到任何