如何知道是使用Callable还是Runnable创建了Future

时间:2019-07-15 15:25:36

标签: java runnable callable

我正在期货交易中投入资金。可以使用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()?

2 个答案:

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

其中FromRunnableFromCallable<T>分别是实现Future<Void>Future<T>的类,它们将所有方法委托给兼容的Future的另一个实例(作为构造函数参数传递) )。

然后您可以使用instanceof检查出处;或通过其他方式,例如扩展提供描述来源的方法的通用基本案例或接口。

但是,重申一下,一种更好的方法是设计您的代码,使其无需知道。

答案 1 :(得分:-2)

可运行没有返回值,而可调用却没有。更多:请阅读HERE