我希望在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并存储结果?
答案 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
执行给定的任务,返回已成功完成的任务的结果(即,不抛出异常),如果有的话。在正常或特殊退货时,未完成的任务将被取消。如果在此操作正在进行时修改了给定集合,则此方法的结果未定义。