Spring Framework上的多线程(或异步)计算
问题内容:
我正在学习Spring Framework,它非常棒。
我想使用JAVA多线程,但是我不知道如何使用Spring Framework。
这是服务代码:
//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循环会导致速度变慢,但是我不知道如何解决这个问题。如果给我一个有用的链接或示例代码,我将不胜感激。
我发现该方法loadStudentHistory与calcStudentGrade(大约30ms)相比非常慢(大约300ms)。
问题答案:
为此,在有并发用户的应用程序中使用多线程是一个坏主意,因为现在每个查询使用多个线程和多个连接,而不是让每个请求使用一个线程和一个连接。它不会随着用户数量的增长而扩展。
在查看您的示例时,我看到两个可能的问题:
1)您在应用程序和数据库之间往返次数过多,每次往返都需要时间。
2)不清楚每个查询是否使用单独的事务(在示例代码中您没有说出事务在何处划定),如果您的查询各自创建自己的事务可能会很浪费,因为每个事务都有相关的开销用它。
使用多线程对#1并没有多大帮助(如果确实有帮助,它将给数据库增加更多的负载),或者对#2没有影响或使其更糟(取决于当前的事务范围;如果您有的话)之前在同一事务中使用多个线程查询,它们将必须在不同事务中进行)。正如已经说明的那样,它不会扩大规模。
我的建议:
1)使服务具有事务性(如果尚未提供),以使它所做的一切都在一次事务中。删除捕获异常/返回空值的东西(这会干扰Spring想要使用异常来回滚事务的方式),并引入异常处理程序,以便捕获并记录从控制器抛出的所有内容。这样可以最大程度地减少创建事务的开销,并使异常处理更简洁。
2)创建一个查询,以带回您的学生列表。这样,将查询一次发送到数据库,然后将结果集结果分块读取(根据结果集上的提取大小)。您可以自定义查询以仅取回您需要的内容,因此您的联接数不会过多。在查询上运行解释计划,并确保它使用索引。您将拥有更快的查询和更少的往返次数,这将大大提高速度。