使用2个线程的更快输出

时间:2017-07-14 06:01:48

标签: java multithreading java-threads completable-future

我希望在Java程序中使用两个线程来完成一小部分工作。我需要第一次调用数据库,第二次调用API,两次使用相同的输入调用,然后使用先完成哪个线程的输出。

这是我第一次使用线程进行编程,而且我非常困惑。我已经看过教程,他们主要解释如何用线程完成两个单独的事情,所以我有点迷失。

有人可以帮助或重新指导我们可能有的任何有用的链接吗?

到目前为止,据我了解,它应该看起来像这样吗? :

Thread thread1 = new Thread(func1());
Thread thread2 = new Thread(func2());
thread1.start();
thread2.start();

但是,我如何提取函数的输出?我怎么知道哪一个先完成了?

-----------更新1 ---------

在尝试CompletableFuture之后(感谢Johan的帮助!)我有这样的事情:

CompletableFuture<Object> getData = CompletableFuture.anyOf(
        CompletableFuture.runAsync(() -> getDataFromDB(clientData)),
        CompletableFuture.runAsync(() -> getDataFromApi(clientData))
    );

    getData.thenApply(dataObject -> {
        // Cast the returned Object to the actual type of your data,
        // assuming both getDataFromDb and getDataFromApi 
        // return the same result type
        Object data = (String) dataObject;

        // Work with the returned data.
        result = (String) data;
    });

但是我得到了getData.thenApply()的错误:

CompletableFuture类型中的方法thenApply(Function)不适用于参数((dataObject) - &gt; {})

因为我知道类型为String的getData,是否可以将其转换为String并存储结果?

3 个答案:

答案 0 :(得分:1)

Java 8 提供了一个非常好的utility class called CompletableFuture,在您的情况下可以提供帮助。

创建两个CompletableFuture,每个任务一个,然后使用CompletableFuture.anyOf方法等待其中一个完成。

CompletableFuture<TData> getData = CompletableFuture.anyOf(
    CompletableFuture.runAsync(() -> getDataFromDb()),
    CompletableFuture.runAsync(() -> getDataFromApi())
);

getData.thenApply(dataObject -> {
    // Cast the returned Object to the actual type of your data,
    // assuming both getDataFromDb and getDataFromApi 
    // return the same result type
    TData data = (TData)dataObject;

    // Work with the returned data.
    processData(data);
});

答案 1 :(得分:1)

正如@Johan Hirsch建议尝试使用CompletableFuture。我只是试试这个并且有效:

    CompletableFuture.anyOf(
            CompletableFuture.supplyAsync(() -> getDataFromDB(clientData)),
            CompletableFuture.supplyAsync(() -> getDataFromApi(clientData)))
            .thenApply(item -> (String) item)
            .thenAccept(result -> {
                // Consume the data
                System.out.println(result);
            });

请注意,我目前消费数据,因此它不会返回任何内容。如果您只想将结果传递给其他CompletableFuture,请更改thenAccept的{​​{1}}方法

答案 2 :(得分:0)

您可以使用ExecutorService.invokeAny

执行给定的任务,返回已成功完成的任务的结果(即,不抛出异常),如果有的话。在正常或特殊退货时,未完成的任务将被取消。如果在此操作正在进行时修改了给定集合,则此方法的结果未定义。