我正在学习 Spring 框架,它非常棒。
我想使用JAVA多线程,但不知道如何使用Spring框架。
这是服务代码:
//StudentService.java
public List<Grade> loadGradesForAllStudents(Date date) {
try{
List<Grade> grades = new ArrayList<Grade>();
List<Student> students = loadCurrentStudents(); // LOAD FROM THE DB
for(Student student : students) { // I WANT TO USE MULTITHREAD FOR THIS PART
// LOAD FROM DB (MANY JOINS)
History studentHistory = loadStudentHistory(student.getStudentId(), date);
// CALCULATION PART
Grade calculatedGrade = calcStudentGrade(studentHistory, date);
grades.add(calculatedGrade);
}
return grades;
} catch(Exception e) {
...
return null;
}
}
如果没有多线程,它会非常慢。
我猜 for 循环导致速度缓慢,但我不知道如何解决这个问题。如果给我一个有用的链接或示例代码,我将不胜感激。
我发现与 calcStudentGrade(大约 30 毫秒)相比,loadStudentHistory 方法相当慢(大约 300 毫秒)。
最佳答案
在具有并发用户的应用程序中,为此使用多线程是一个坏主意,因为现在每个查询都使用多个线程和多个连接,而不是让每个请求使用一个线程和一个连接。它不会随着用户数量的增长而扩展。
当我查看您的示例时,我发现两个可能的问题:
1) 应用程序和数据库之间的往返次数过多,每次往返都需要时间。
2)不清楚每个查询是否使用单独的事务(您没有说明示例代码中划分事务的位置),如果您的查询每个都创建自己的事务,这可能会造成浪费,因为每个事务有与之相关的开销。
使用多线程对#1 没有多大帮助(如果确实有帮助,则会给数据库带来更多负载),并且对#2 没有任何影响,或者会使情况变得更糟(取决于当前的事务范围;如果您之前在同一事务中进行过查询,那么使用多个线程它们必须位于不同的事务中)。正如已经解释的那样,它不会扩大规模。
我的建议:
1) 使服务成为事务性的(如果还不是事务性的),以便它所做的一切都在一个事务内。删除异常捕获/空返回的内容(这会干扰 Spring 使用异常回滚事务的方式)并引入异常处理程序,以便捕获并记录从 Controller 抛出的任何内容。这将最大限度地减少创建事务的开销并使异常处理更加清晰。
2) 创建一个查询来返回学生列表。这样,查询会发送到数据库一次,然后结果集结果会分块读回(根据结果集的获取大小)。您可以自定义查询以仅返回您需要的内容,这样就不会出现过多的联接。对查询运行解释计划并确保它使用索引。您将获得更快的查询速度和更少的往返次数,这将大大提高速度。
关于java - Spring框架上的多线程(或异步)计算,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25673959/