首页 > 解决方案 > 如何同时开始一些搜索

问题描述

我目前正在开发一个前端,用于在外国系统中的一些搜索中可视化结果。目前,该程序正在逐个询问一个系统,并且只有在所有外部系统都已回答时才继续。前端是用 Vaadin 13 编写的,应该可以通过推送刷新页面。

我有六个控制器类要针对六个外部系统提出问题,并且希望同时开始所有问题,而不必等待前一个控制器完成。

我的问题是我找不到可以帮助我解决这个特殊问题的教程。所有教程都是关于不止一次但同时启动相同的过程。

这就是我现在开始搜索的方式:

public static void performSingleSearch(ReferenceSystem referenceSystem, String searchField, List<String> searchValues, SystemStage systemStage) throws Exception {

    if(!isAvailable(referenceSystem, systemStage)) return;
    Map<String, ReferenceElement> result = new HashMap<>();
    try {
        Class<?> classTemp = Class.forName(referenceSystem.getClassname());
        Method method = classTemp.getMethod("searchElements", String.class , List.class, SystemStage.class);
        result = (Map<String, ReferenceElement>) method.invoke(classTemp.newInstance(), searchField, searchValues, systemStage);
    } catch (Exception e) { 
        return;
    }
    if(result != null) orderResults(result, referenceSystem);
}

我希望你能给我一个关于如何使用多线程的教程,或者更好的一本书。

最好的问候丹尼尔

标签: javamultithreading

解决方案


在我看来,最简单的方法是使用CompletableFuture. 忽略你对反射的残忍使用,我假设

interface ReferenceSystem {
    public Map<String,ReferenceElement> searchElements(List<String> args);
}

List<ReferenceSystem> systems = getSystems();
List<String> searchArguments = getSearchArguments();

所以你可以做

List<CompletableFuture<Map<String, ReferenceElement>>> futures = new ArrayList<>();
for (ReferenceSystem system : systems) {
    futures.add(CompletableFuture.supplyAsync(() -> system.searchElements(searchArguments)));
}

或使用 Java 8 流

List<CompletableFuture<Map<String, ReferenceElement>>> futures =
    systems.stream()
           .map(s -> CompletableFuture.supplyAsync(
                     () -> system.searchElements(searchArguments)))
           .collect(Collectors.toList());

现在futures包含一个期货列表,最终将返回Map您正在寻找的;您可以访问它们,#get()它们将阻塞直到结果出现:

for (CompletableFuture<Map<String,ReferenceElement>> future : futures) {
    System.out.printf("got a result: %s%n", future.get());
}

推荐阅读