Java并发查询
我正在用 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;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
这里有两个问题:
invokeAll()
或awaitTermination()
之类的方法来为您执行此操作。要获取ExecutorService
,请使用Executors
类中的方法。此类还提供将 Runnable 包装为 Callable 的方法。因此,在 main 方法中,您将创建一个ExecutorService
,在 for 循环中提交所有可运行对象,调用shutdown()
和awaitTermination()
。然后,打印计数器的值。Runnable
实例使用自己的秒表非常重要,因此stopwatch2
变量需要是run()
的局部变量。另外,counter
变量不能是普通的 long,但它需要是 AtomicLong。否则,某些线程的时间可能会丢失,因为正常的加法不是原子操作(两个线程可能会尝试同时将其时间添加到计数器变量,这可能会导致错误的结果)。这是代码:
There are two problems here:
invokeAll()
orawaitTermination()
that do this for you. To get anExecutorService
, use the methods from theExecutors
class. This class also offers methods to wrapRunnable
intoCallable
. So in the main method you would create anExecutorService
, submit all the runnables in the for loop, callshutdown()
andawaitTermination()
. Then, print the value of the counter.Runnable
instance uses its own stopwatch, so thestopwatch2
variable needs to be a local variable ofrun()
. Also, thecounter
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:
如果您在线程之间共享相同的 SQL 连接,那么这可能是您的问题。一般来说,您应该避免在不同线程之间共享相同的连接,而应使用连接池。
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.
您描述的行为最可能的原因是
dataHandler.selectData()
要么是synchronized
要么依赖synchronized
方法来完成工作。要解决这个问题,您要么需要删除同步(显然不会破坏任何东西),要么每个线程有一个单独的 dataHandler (前提是相关类支持这一点。)
The most likely cause of the behaviour you describe is that
dataHandler.selectData()
either issynchronized
or relies on asynchronized
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.)