首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java并发查询

Java并发查询
EN

Stack Overflow用户
提问于 2011-03-09 11:00:40
回答 3查看 7.3K关注 0票数 1

我正在用Java构建一个基准应用程序作为实验。该工具的目的是了解特定数据库(例如Derby、MySQL )在不同设置下的速度。

目前,我正试图了解数据库在同时执行多个查询时的速度。

我想创建多个线程,其中每个线程执行多个查询。但目前,查询似乎是在其他查询完成之后执行的,而不是并发执行的。

我有以下(简化的)代码:

代码语言:javascript
复制
Runner testCase = new Runner();

for (int i = 0; i < THREAD_COUNT; i++) {
    Thread testThread = new Thread(testCase);
    testThread.start();
}

public class Runner implements Runnable {

    public void run() {

      for (int i = 0; i < Benchmarker.QUERY_COUNT; i++) {

        stopwatch2.start();
        List<Person> selectData = dataHandler.selectData();
        stopwatch2.stop();
        counter += stopwatch2.getStopwatchValue();

       }
    }
}

我的测试系统的cpu有两个核心,所以应该可以一次运行两个多线程,对吗?

有人知道如何实现这个选项吗?

谢谢你的时间和帮助!

更新-添加了selectData方法代码

代码语言:javascript
复制
public List<Person> selectData() {

List<Person> data = new ArrayList<Person>();

try {
    // Select all persons from the database
    ResultSet resultSet = connection.prepareStatement("SELECT * FROM PERSON ORDER BY name").executeQuery();

    // Add all the persons to a arraylist
    while (resultSet.next()) {
    data.add(new Person(resultSet.getString("name")));
    }

    // Close the resultset
    resultSet.close();

} catch (SQLException ex) {
    Logger.getLogger(Derby.class.getName()).log(Level.SEVERE, null, ex);
}

return data;
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-03-09 12:21:51

这里有两个问题:

  1. 你必须等到所有的线都完成。这可以手动完成,但是不使用线程要容易得多,而是一个ExecutorService,它为您提供了invokeAll()awaitTermination()之类的方法。要获得ExecutorService,请使用Executors类中的方法。这个类还提供了将Runnable包装到Callable中的方法。因此,在main方法中,您将创建一个ExecutorService,提交for循环中的所有runnables,调用shutdown()awaitTermination()。然后,打印计数器的值。
  2. 你必须注意正确地增加时间。为此,每个Runnable实例使用自己的秒表非常重要,因此stopwatch2变量需要是run()的局部变量。而且,counter变量不能是普通长,但它需要是一个AtomicLong。否则,某些线程的时间可能会丢失,因为正常的加法不是原子操作(两个线程可能同时尝试将它们的时间添加到计数器变量中,这可能会导致错误的结果)。

下面是代码:

代码语言:javascript
复制
void runTests() {
  Runner testCase = new Runner();
  ExecutorService executor = Executors.newCachedThreadPool();

  for (int i = 0; i < THREAD_COUNT; i++) {
    executor.execute(testCase);
  }
  executor.shutdown();
  executor.awaitTermination(60, TimeUnit.SECONDS);
  System.out.println(counter.toString());
}

private AtomicLong counter = new AtomicLong();

public class Runner implements Runnable {

    public void run() {
      StopWatch stopwatch2 = ... // get a stopwatch instance here

      for (int i = 0; i < Benchmarker.QUERY_COUNT; i++) {

        stopwatch2.start(); // this needs to reset the stopwatch to 0
        List<Person> selectData = dataHandler.selectData();
        stopwatch2.stop();
        counter.addAndGet(stopwatch2.getStopwatchValue());

       }
    }
}
票数 4
EN

Stack Overflow用户

发布于 2011-03-09 12:02:42

如果您在线程之间共享相同的SQL连接,那么这可能是您的问题。通常,您应该避免在不同线程之间共享相同的连接,而应该使用连接池。

票数 3
EN

Stack Overflow用户

发布于 2011-03-09 11:13:15

您所描述的行为最有可能的原因是dataHandler.selectData()要么是synchronized,要么是依赖于synchronized方法来完成这项工作。

要解决这个问题,您要么需要删除同步(显然没有破坏),要么每个线程都有一个单独的dataHandler (如果相关的类支持这一点)。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5244782

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档