如何知道 Future 是使用 Callable 还是 Runnable 创建的
How to know if a Future is created with Callable or Runnable
我正涉足 Futures。可以使用 Runnable 和 Callable 创建 Future。有没有办法决定它是如何创建的?
比如我有如下代码:
Future<?> future = null;
Future<?> future2 = null;
ExecutorService service = null;
service = Executors.newSingleThreadExecutor();
future = service.submit(() -> {
for (int i = 0; i < 5; ++i) {
System.out.println("Printing record: " + i);
Thread.sleep(5);
}
return "Done";
});
future2 = service.submit(() -> System.out.println("Printing zoo inventory"));
System.out.println("================================================================");
System.out.println(future);
System.out.println(future.get().getClass());
System.out.println(future.get());
System.out.println("================================================================");
System.out.println(future2);
try {
System.out.println(future2.get().getClass());
System.out.println(future2.get());
} catch (ExecutionException e) {
System.out.println("Could not do a get");
}
System.out.println("================================================================");
结果为:
================================================================
java.util.concurrent.FutureTask@5caf905d[Completed normally]
class java.lang.String
Done
================================================================
java.util.concurrent.FutureTask@1f32e575[Completed normally]
Exception in thread "main" java.lang.NullPointerException
at ZooInfo.main(ZooInfo.java:56)
我可以使用以下方法解决这个问题:
if (future2.get() == null) {
System.out.println("Made with a Runnable");
} else {
System.out.println(future2.get().getClass());
System.out.println(future2.get());
}
问题在于,当Runnable 还需要一些时间时,我就白等了。有没有办法在不使用 get() 的情况下确定 Future 是使用 Runnable 还是 Callable 创建的?
我不认为您真的需要知道 Future
是从 Runnable
还是 Callable
创建的。
一方面,创建 Future
的方法不止于此:例如,CompleteableFuture
都不是从中创建的;而且,更一般地说,由于 Future
是一个接口,因此您可以根据需要创建实例。
对于另一个:Future
的抽象是它在完成或抛出异常时为您提供(可能为 null)值。这就是它的全部目的。
(此外,您当前检查 return 值是否为空的方法无法可靠地工作,因为 Callable.call()
被允许 return 为空)。
如果您需要它做其他事情,您可能需要重新审视您的设计,这样您就可以简单地按预期处理它。
但是如果您确实有一个用例需要您知道它是如何创建的,那么您需要控制创建。与其让调用者直接向执行者提交代码,不如像这样包裹在 class 中:
class YourExecutor {
// Initialize in ctor.
private final ExecutorService executor;
FromRunnable submit(Runnable r) {
return new FromRunnable(executor.submit(r));
}
<T> FromCallable<T> submit(Callable<? extends T> c) {
return new FromCallable<>(executor.submit(c));
}
}
其中 FromRunnable
和 FromCallable<T>
是 classes 分别实现 Future<Void>
和 Future<T>
,它们将所有方法委托给兼容的另一个实例Future(作为构造函数参数传递)。
然后您可以使用 instanceof
检查出处;或者通过一些其他方式,例如扩展一个通用的基本案例或接口,它提供了一种描述出处的方法。
但是,重申一下,更好的方法是设计您的代码,使其不需要知道。
我正涉足 Futures。可以使用 Runnable 和 Callable 创建 Future。有没有办法决定它是如何创建的?
比如我有如下代码:
Future<?> future = null;
Future<?> future2 = null;
ExecutorService service = null;
service = Executors.newSingleThreadExecutor();
future = service.submit(() -> {
for (int i = 0; i < 5; ++i) {
System.out.println("Printing record: " + i);
Thread.sleep(5);
}
return "Done";
});
future2 = service.submit(() -> System.out.println("Printing zoo inventory"));
System.out.println("================================================================");
System.out.println(future);
System.out.println(future.get().getClass());
System.out.println(future.get());
System.out.println("================================================================");
System.out.println(future2);
try {
System.out.println(future2.get().getClass());
System.out.println(future2.get());
} catch (ExecutionException e) {
System.out.println("Could not do a get");
}
System.out.println("================================================================");
结果为:
================================================================
java.util.concurrent.FutureTask@5caf905d[Completed normally]
class java.lang.String
Done
================================================================
java.util.concurrent.FutureTask@1f32e575[Completed normally]
Exception in thread "main" java.lang.NullPointerException
at ZooInfo.main(ZooInfo.java:56)
我可以使用以下方法解决这个问题:
if (future2.get() == null) {
System.out.println("Made with a Runnable");
} else {
System.out.println(future2.get().getClass());
System.out.println(future2.get());
}
问题在于,当Runnable 还需要一些时间时,我就白等了。有没有办法在不使用 get() 的情况下确定 Future 是使用 Runnable 还是 Callable 创建的?
我不认为您真的需要知道 Future
是从 Runnable
还是 Callable
创建的。
一方面,创建 Future
的方法不止于此:例如,CompleteableFuture
都不是从中创建的;而且,更一般地说,由于 Future
是一个接口,因此您可以根据需要创建实例。
对于另一个:Future
的抽象是它在完成或抛出异常时为您提供(可能为 null)值。这就是它的全部目的。
(此外,您当前检查 return 值是否为空的方法无法可靠地工作,因为 Callable.call()
被允许 return 为空)。
如果您需要它做其他事情,您可能需要重新审视您的设计,这样您就可以简单地按预期处理它。
但是如果您确实有一个用例需要您知道它是如何创建的,那么您需要控制创建。与其让调用者直接向执行者提交代码,不如像这样包裹在 class 中:
class YourExecutor {
// Initialize in ctor.
private final ExecutorService executor;
FromRunnable submit(Runnable r) {
return new FromRunnable(executor.submit(r));
}
<T> FromCallable<T> submit(Callable<? extends T> c) {
return new FromCallable<>(executor.submit(c));
}
}
其中 FromRunnable
和 FromCallable<T>
是 classes 分别实现 Future<Void>
和 Future<T>
,它们将所有方法委托给兼容的另一个实例Future(作为构造函数参数传递)。
然后您可以使用 instanceof
检查出处;或者通过一些其他方式,例如扩展一个通用的基本案例或接口,它提供了一种描述出处的方法。
但是,重申一下,更好的方法是设计您的代码,使其不需要知道。