如何同时开始一些搜索

时间:2019-06-06 09:59:46

标签: java multithreading

我目前正在研究前端,以便在外部系统中进行某些搜索后可视化结果。目前,程序正在另一个系统中询问一个系统,并且仅在所有外部系统都已回答时才继续。 前端是用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);
}

希望您能为我提供有关如何进行编程的教程,或者最好是多线程方面的书。

最好的问候 丹尼尔

2 个答案:

答案 0 :(得分:1)

在我看来,最简单的方法是使用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());
}

答案 1 :(得分:0)

在原始情况下,您需要的只是线程列表,然后等待它们完成甚至更简单,请使用线程池并使用它:

private static ExecutorService service = Executors.newFixedThreadPool(6); // change to whatever you want

public static void someMethod() {
    queueActions(Arrays.asList(
            () -> {
                try {
                    performSingleSearch(null, null, null, null); // fill your data
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } 
            }, 
            () -> {
                try {
                    performSingleSearch(null, null, null, null); // fill your data #2 etc
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } 
            }
    ));
}

public static void queueActions(List<Runnable> actions) {
    Semaphore wait = new Semaphore((-actions.size()) + 1);

    for (Runnable action : actions) {
        service.execute(() -> {
            try {
                action.run();
            } finally {
                wait.release();
            }
        });
    }

    try {
        wait.acquire();
    } catch (InterruptedException e) {

    }
}

问题仍然存在,您是要同时执行订单还是一次执行一个订单或其他(将订单合并为一个大订单,等等)。