【问题标题】:Starting mupltiple threads and collect the results启动多个线程并收集结果
【发布时间】:2019-06-19 05:02:29
【问题描述】:

我有一个接口,用于在 ENUM 收集的某些子系统中进行搜索。界面如下所示:

public interface ReferenceController {

    public Map<String, ReferenceElement> searchElements(String searchField, List<String> searchItems, SystemStage systemStage) throws Exception;

    public Boolean isAvailable(SystemStage systemStage) throws Exception;

    public Boolean isAvailable(SystemStage systemStage) throws Exception;
}

ENUM 看起来像这样

public enum ReferenceSystem implements ReferenceController{
    UCMDB    (UcmdbFunctions.class),
    PROIPS   (ProIPSFunctions.class),
    KV       (KvFunctions.class),
    FISERVICE(FiServiceFunctions.class),
    COMMAND  (CommandFunctions.class),
    FII          (FiiFunctions.class);

    private Class<? extends ReferenceController> clazz;

    private ReferenceSystem(Class<? extends ReferenceController> controllerClass) {
        this.clazz = controllerClass;
    }

    public String displayName() {
        return displayName(Locale.GERMAN); 
    }

    public String displayName(Locale locale) {
        ResourceBundle bundle = ResourceBundle.getBundle("EnumI18n", locale);
        return bundle.getString(toString()); 
    }

    public Class<? extends ReferenceController> getClassname() { return clazz; }

    @Override
    public Map<String, ReferenceElement> searchElements(String searchField, List<String> searchItems, SystemStage systemStage) throws Exception {
        Map<String, ReferenceElement> result = clazz.newInstance().searchElements(searchField, searchItems, systemStage);
        return result;
    }

    @Override
    public String getStateMapping(String value) {
        try {
            return clazz.newInstance().getStateMapping(value);
        } catch (IllegalAccessException | InstantiationException e) {
            return null;
        }
    }

    @Override
    public Boolean isAvailable(SystemStage systemStage) throws Exception {
        return clazz.newInstance().isAvailable(systemStage);
    }
}

此刻我开始一个接一个地搜索。所以我的服务器必须等待搜索完成才能开始下一个搜索。因此,用户必须等待很长时间才能显示结果。 此代码开始搜索

    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 {
            result = referenceSystem.searchElements(searchField, searchValues, systemStage);
        } catch (Exception e) { 
            return;
        }
        if(result != null) orderResults(result, referenceSystem);
    }

resultmap 是所有子系统的同一个对象,所以我需要一个系统,所有搜索都立即开始,并且能够将它们的结果放入结果对象中。

我希望可以几乎同步地填充这些对象,这样用户就不必等待所有系统完成。

最好的问候 丹尼尔

【问题讨论】:

标签: java multithreading


【解决方案1】:

如果您愿意使用Guava,您可以使用ListeningExecutorService.submit 提交一个Callable 包装每个对searchElements 的调用,并将返回的ListenableFuture 实例收集到一个列表中。使用Futures.allAsList,可以将列表转换为如果所有期货成功完成则返回所有结果列表的未来,否则将不成功完成。

例如:

<T> void submitAll(
        Collection<Callable<T>> callables,
        Consumer<List<T>> onSuccess,
        Consumer<Throwable> onError,
        ExecutorService executor) {

    ListeningExecutorService decoratedExecutor = MoreExecutors.listeningDecorator(executor);

    List<ListenableFuture<T>> futures = Lists.newArrayList();
    for (Callable<T> callable : callables) {
        futures.add(decoratedExecutor.submit(callable));
    }

    FutureCallback<? super List<T>> cb = new FutureCallback<List<T>>() {
        public void onSuccess(List<T> result) {
            onSuccess.accept(result);
        }

        public void onFailure(Throwable t) {
            onError.accept(t);
        }
    };

    Futures.addCallback(Futures.allAsList(futures), cb, executor);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-26
    • 1970-01-01
    • 2017-02-22
    • 2022-12-11
    相关资源
    最近更新 更多