【问题标题】:get query behind each executorservice thread在每个 executorservice 线程后面获取查询
【发布时间】:2015-12-30 08:17:09
【问题描述】:

我在 JAVA 中使用 executorsevice 来执行一些线程,比如说十个线程,线程数可能会有所不同。每个线程都在执行一个 SQL 服务器查询。我正在使用 Future 和 Callable 类来提交任务。一旦每个线程完成,我就会得到结果 [使用 future.get()]。

现在我的要求是我需要知道每个线程在返回结果后执行的查询,即使结果是空集。

这是我的代码:

List<Future<List>> list = new ArrayList<Future<List>>();
    int totalThreads = allQueriesWeight.size();
    ExecutorService taskExecutor = Executors.newFixedThreadPool(totalThreads);
    for (String query : allQueriesWeight) {//allQueriesWeight is an arraylist containing sql server queries
        SearchTask searchTask = new SearchTask(query);
        Future<List> submit = taskExecutor.submit(searchTask);
        list.add(submit);
    }

这是我的调用函数:

@Override
public List<SearchResult> call() throws Exception {
    java.sql.Statement statement = null;
    Connection co = null;
    List<SearchResult> allSearchResults = new ArrayList();
    try {
        //executing query and getting results
        while (r1.next()) {
            ...
            allSearchResults.add(r);//populating array
        }
    } catch (Exception e) {
        Logger.getLogger(GenericResource.class.getName()).log(Level.SEVERE, null, e);
    } finally {
        if (statement != null) {
            statement.close();
        }
        if (co != null) {
            co.close();
        }
    }
    return allSearchResults;
}

这是我得到结果的方式:

for (Future<List> future : list) {
        try {
            System.out.println(future.get().size());
            List<SearchResult> sr = future.get();
        } catch (InterruptedException ex) {
            Logger.getLogger(GenericResource.class.getName()).log(Level.SEVERE, null, ex);
        } catch (ExecutionException ex) {
            Logger.getLogger(GenericResource.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

在上面的这个for循环中,我需要识别返回结果的查询。我是新手,非常感谢任何帮助/建议。

谢谢。

【问题讨论】:

  • list 将包含与您向 Executor 提交查询的顺序完全相同的结果,因此您可以将它们与 allQueriesWeight 匹配。
  • 但是您的 SeaatchTask 已通过查询?所以你可能也想把它传递给 SearchResult?
  • 定义一个包含执行结果列表以及任何性能度量(即线程 ID、执行时间等)的类还不够简单吗?然后,您可以返回该类对象作为您的 callable 的结果。

标签: java multithreading executorservice


【解决方案1】:

备选方案 1: 您有两个列表的顺序和大小相同,因此您可以简单地执行以下操作

for (int i = 0; i < allQueriesWeight.size(); i++) {
    allQueriesWeight.get(i);
    futureList.get(i);
}

备选方案 2: 如果所有查询都不一样,可以使用如下图的映射,但是这种方式会丢失执行顺序。

int totalThreads = allQueriesWeight.size();
Map<String,Future<List>> map = new HashMap<>;
ExecutorService taskExecutor = Executors.newFixedThreadPool(totalThreads);
for (String query : allQueriesWeight) {//allQueriesWeight is an arraylist containing sql server queries
    SearchTask searchTask = new SearchTask(query);
    Future<List> submit = taskExecutor.submit(searchTask);
    map.put(query ,submit );
}

然后迭代地图

for (Entry<String,Future<List>> future : map.) {
    System.out.println("query is:" +map.getKey());
    List<SearchResult> sr = map.getValue().get();

}

备选方案 3 如果要保持顺序,请创建一个以 Future 和查询为属性的类,然后将该类放入列表中

   public class ResultWithQuery {

    private final Future<List<?>> future;
    private final  String query;


    public ResultWithQuery(Future<List<?>> future, String query) {
        this.future = future;
        this.query = query;
    }


    public Future<List<?>> getFuture() {
        return future;
    }


    public String getQuery() {
        return query;
    }

}

还有

List<ResultWithQuery > list = new ArrayList<ResultWithQuery >();
    int totalThreads = allQueriesWeight.size();
    ExecutorService taskExecutor = Executors.newFixedThreadPool(totalThreads);
    for (String query : allQueriesWeight) {//allQueriesWeight is an arraylist containing sql server queries
        SearchTask searchTask = new SearchTask(query);
        Future<List> submit = taskExecutor.submit(searchTask);
        list.add(new ResultWithQuery (submit, query));
    }

并迭代列表

for (ResultWithQuery resQuery: list) {
        try {
            resQuery.getQuery();
            List<SearchResult> sr = resQuery.getFuture.get();
        } catch (InterruptedException ex) {
            Logger.getLogger(GenericResource.class.getName()).log(Level.SEVERE, null, ex);
        } catch (ExecutionException ex) {
            Logger.getLogger(GenericResource.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

【讨论】:

  • 这正是我们想要的。它解决了我的问题。非常感谢您的详细回答。
猜你喜欢
  • 2011-11-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-01
  • 2020-02-22
  • 1970-01-01
相关资源
最近更新 更多