开发者

Java concurrent queries

开发者 https://www.devze.com 2023-02-15 22:16 出处:网络
I´m building a benchmarkapplication in Java as experiment. The purpose of the tool is to find out how fast a specific database (like Derby, MySQL for example) is in different s开发者_如何转开发etting

I´m building a benchmarkapplication in Java as experiment. The purpose of the tool is to find out how fast a specific database (like Derby, MySQL for example) is in different s开发者_如何转开发ettings.

At the moment I'm trying to find out how fast a database is when executing multiple queries at the same time.

I thought of creating multiple threads where each thread executes multiple queries. But at the moment the queries seems to be executed after the other query is finished instead of concurrently.

I've got the following (simplified) code:

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

       }
    }
}

The cpu of mine testsystem has two cores so it should be possible to run two multiple threads at a time, right?

Somebody an idea how to implement this option?

Thank you for your time and help!

UPDATE - added selectData method code:

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


There are two problems here:

  1. You have to wait until all Threads have finished. This can be done manually, but it is much easier to not use Threads, but an ExecutorService which offers you methods like invokeAll() or awaitTermination() that do this for you. To get an ExecutorService, use the methods from the Executors class. This class also offers methods to wrap Runnable into Callable. So in the main method you would create an ExecutorService, submit all the runnables in the for loop, call shutdown() and awaitTermination(). Then, print the value of the counter.
  2. You have to take care of adding the times correctly. For this it is important that each Runnable instance uses its own stopwatch, so the stopwatch2 variable needs to be a local variable of run(). Also, the counter variable cannot be a normal long, but it needs to be an AtomicLong. Otherwise the times of some threads could get lost, because normal addition is not an atomic operation (two threads could try to add their times to the counter variable at the same time, which would probably cause a wrong result).

Here's the code:

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

       }
    }
}


If you share the same SQL Connection between the threads then that might be your problem. In general you should avoid sharing the same connection between different threads and use connection pools instead.


The most likely cause of the behaviour you describe is that dataHandler.selectData() either is synchronized or relies on a synchronized method do the work.

To solve this, you either need to remove the synchronization (obviously without breaking things), or have a separate dataHandler per thread (provided the class in question supports that.)

0

精彩评论

暂无评论...
验证码 换一张
取 消