我正在期货交易中投入资金。可以使用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仍然需要一些时间时,我正在等待获取任何东西。有没有一种方法可以确定是使用Runnable还是Callable创建了Future,而又没有使用get()?
答案 0 :(得分:2)
我不认为您真的需要知道Future
是从Runnable
还是Callable
创建的。
一方面,创建Future
的方法不止一种:例如,CompleteableFuture
并不是从任何一个创建的;而且,由于Future
是一个接口,因此可以根据需要创建实例。
另一个:Future
的抽象之处在于,它可以在完成或引发异常时为您提供(可能为null)值。这就是它要做的全部。
(此外,由于允许Callable.call()
返回null,因此您当前检查返回值是否为null的方法也不可靠。
如果您需要它做其他事情,则可能需要重新访问设计,以便您可以按预期进行处理。
但是,如果您确实有一个用例,确实需要您知道它是如何创建的,则需要控制创建。而不是让调用者将代码直接提交给执行者,而是包装如下这样的类:
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>
分别是实现Future<Void>
和Future<T>
的类,它们将所有方法委托给兼容的Future的另一个实例(作为构造函数参数传递) )。
然后您可以使用instanceof
检查出处;或通过其他方式,例如扩展提供描述来源的方法的通用基本案例或接口。
但是,重申一下,一种更好的方法是设计您的代码,使其无需知道。
答案 1 :(得分:-2)
可运行没有返回值,而可调用却没有。更多:请阅读HERE