Java并发查询

标签 java multithreading concurrency benchmarking

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

目前,我正在尝试找出同时执行多个查询时数据库的速度。

我想创建多个线程,每个线程执行多个查询。但目前查询似乎是在另一个查询完成后执行的,而不是同时执行的。

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

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 方法代码:

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;
}

最佳答案

这里有两个问题:

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

代码如下:

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());

       }
    }
}

关于Java并发查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5244782/

相关文章:

java - AsyncTask-Method getText 必须从 UI 线程调用

java - 使用 AsyncTask 时出现 ExceptionInInitializerError

java - 如何在intellij中纠正java多行中单个语句的缩进

java - 在 FileWriter - Java 中设置编码的替代方法

Java8 CompletableFuture 条件链

concurrency - MVCC & B-Tree & 并发

java - 对 ReentrantReadWriteLock#tryLock 失败的 jcstress 测试感到困惑

java - 如何在两个 Observable 之间重用订阅者 (RxJava)

python - 如何检查线程当前是否持有 GIL?

java - 如何解决java中的无效线程访问