Spring Framework上的多线程(或异步)计算

Kim*_*Man 2 java spring multithreading asynchronous spring-mvc

我正在学习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;
    }
}
Run Code Online (Sandbox Code Playgroud)

没有多线程,它很慢.

我想for循环会导致缓慢,但我不知道如何解决这个问题.如果给我一个有用的链接或示例代码,我会很感激.

我发现loadStudentHistory方法与calcStudentGrade(大约30ms)相比非常慢(大约300ms).

Nat*_*hes 5

在具有并发用户的应用程序中使用多线程这是一个坏主意,因为现在每个查询使用多个线程和多个连接,而不是让每个请求使用一个线程和一个连接.它不会随着用户数量的增长而扩展.

当我看你的例子时,我看到两个可能的问题:

1)您在应用程序和数据库之间进行了太多的往返,其中每次旅行都需要时间.

2)目前尚不清楚每个查询是否使用单独的事务(您没有说明在示例代码中划分事务的位置),如果您的查询每个都创建自己的事务可能会浪费,因为每个事务都有相关的开销用它.

使用多线程对#1(如果它确实有助于它会对数据库施加更多负载)没有太大帮助,并且对#2没有影响或使其变得更糟(取决于当前的事务范围;如果你有之前在同一事务中的查询,使用多个线程,它们必须在不同的事务中).如前所述,它不会扩大规模.

我的建议:

1)使服务具有事务性(如果尚未进行),以便它所做的一切都在一个事务中.删除异常捕获/返回null的东西(这会干扰Spring如何使用异常来回滚事务)并引入异常处理程序,以便捕获并记录从控制器抛出的任何内容.这将最大限度地减少您创建事务的开销,并使您的异常处理更加清晰.

2)创建一个带回学生列表的查询.这样查询就会被发送到数据库一次,然后结果集结果以块的形式回读(根据结果集上的获取大小).您可以自定义查询以仅返回您需要的内容,这样您就不会有过多的连接数.对查询运行explain-plan并确保它使用索引.您将获得更快的查询和更少的往返次数,这将大大提高速度.