Java Spring Boot@异步同步运行

Java Spring Boot@异步同步运行,java,spring,spring-mvc,asynchronous,Java,Spring,Spring Mvc,Asynchronous,我在这里看到了一些类似的问题,但它们的解决方案都不起作用。我的两个异步调用同步运行 HomeController.java @Controller @EnableOAuth2Sso public class HomeController { @Autowired private ProjectService projectService; @RequestMapping("/") public String home(Model model) { Future<List<

我在这里看到了一些类似的问题,但它们的解决方案都不起作用。我的两个异步调用同步运行

HomeController.java

@Controller
@EnableOAuth2Sso
public class HomeController {

@Autowired
private ProjectService projectService;

@RequestMapping("/")
public String home(Model model) {
    Future<List<Project>> latest = projectService.getLatest();
    Future<List<Project>> popular = projectService.getPopular();

    try {
        while (!(latest.isDone() && popular.isDone())) {
            Thread.sleep(10); //10-millisecond pause between each check
        }

        model.addAttribute("latest", latest.get());
        model.addAttribute("popular", popular.get());
    } catch(Exception e) {
        System.out.println("ERROR in async thread " + e.getMessage());
    }

    return "home";
 }
}
@Service
public class ProjectService {

@Autowired
private MessageSendingOperations<String> messagingTemplate;

@Autowired
private ProjectRepository projectRepository;

@Async("taskExecutor")
public Future<List<Project>> getLatest() {
    return new AsyncResult<List<Project>>(this.projectRepository.getLatest());
}

@Async("taskExecutor")
public Future<List<Project>> getPopular() {
    return new AsyncResult<List<Project>>(this.projectRepository.getPopular());
}
@Component
public class ProjectRepository {

public List<Project> getLatest() {
    return this.generateData(); // 10 seconds to generate random data
}

public List<Project> getPopular() {
    return this.generateData();  // 10 seconds to generate random data
}

 public List<Project> generateData() {
    try { Thread.sleep(10000); } catch(Exception e) {}

    ArrayList<Project> projects = new ArrayList<Project>();
    ArrayList<Repository> repositories = new ArrayList<Repository>();

    repositories.add(
            new Repository("repo-name1", "repo-url-1")
    );
    repositories.add(
            new Repository("repo-name2", "repo-url-2")
    );

    projects.add(
            new Project("title10", "description10")
                    .setViews(new Random().nextInt(10000))
                    .setRepositories(repositories)
    );
    projects.add(new Project("title20", "description20").setViews(new Random().nextInt(1000)));

    projects.add(new Project("title", UUID.randomUUID().toString()).setViews(new Random().nextInt(100)));

    return projects;
}
}
@Configuration
@EnableAsync
public class AsyncConfig {

@Value("${pool.size:10}")
private int poolSize;;

@Value("${queue.capacity:10}")
private int queueCapacity;

@Bean(name="taskExecutor")
public TaskExecutor taskExecutor() {
    ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
    taskExecutor.setMaxPoolSize(this.poolSize);
    taskExecutor.setQueueCapacity(this.queueCapacity);
    taskExecutor.afterPropertiesSet();
    return new ThreadPoolTaskExecutor();
}
}
如果运行async,来自控制器的两个服务调用都需要大约10秒,但仍然需要20秒-我缺少什么?

请忽略简单和愚蠢,没有接口等,我尽可能地删除,以尝试隔离问题。我最初遵循官方文件


GitHub上的代码:

下面是一个基于您的代码的简单而有效的测试用例(它适合从命令行运行):

项目类

package test.springAsync;

public class Project {
    private String name;

    public Project(String title, String description) {

    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Project setViews(int value) {
        return this;
    }

}
ProjectRepository类:

package test.springAsync;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.UUID;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
@Component
public class ProjectRepository {
    private Logger logger=LoggerFactory.getLogger(ProjectRepository.class.getName());

    public List<Project> getLatest() {
        return this.generateData(); // 10 seconds to generate random data
    }

    public List<Project> getPopular() {
        return this.generateData(); // 10 seconds to generate random data
    }

    public List<Project> generateData() {
        logger.debug("generateData start");
        try {
            Thread.sleep(10000);
        } catch (Exception e) {
        }

        ArrayList<Project> projects = new ArrayList<Project>();


        projects.add(new Project("title10", "description10").setViews(new Random().nextInt(10000)));
        projects.add(new Project("title20", "description20").setViews(new Random().nextInt(1000)));

        projects.add(new Project("title", UUID.randomUUID().toString()).setViews(new Random().nextInt(100)));
        logger.debug("generateData end");
        return projects;
    }
}
最后是main的输出:

2015-10-16 09:16:19,231 [main] DEBUG test.springAsync.TestAsyncBean - start Home 
2015-10-16 09:16:19,244 [testExecutor1] DEBUG test.springAsync.ProjectRepository - generateData start 
2015-10-16 09:16:19,244 [testExecutor2] DEBUG test.springAsync.ProjectRepository - generateData start 
2015-10-16 09:16:20,236 [main] DEBUG test.springAsync.TestAsyncBean - waiting for AsyncMethods 
2015-10-16 09:16:21,236 [main] DEBUG test.springAsync.TestAsyncBean - waiting for AsyncMethods 
2015-10-16 09:16:22,236 [main] DEBUG test.springAsync.TestAsyncBean - waiting for AsyncMethods 
2015-10-16 09:16:23,236 [main] DEBUG test.springAsync.TestAsyncBean - waiting for AsyncMethods 
2015-10-16 09:16:24,236 [main] DEBUG test.springAsync.TestAsyncBean - waiting for AsyncMethods 
2015-10-16 09:16:25,236 [main] DEBUG test.springAsync.TestAsyncBean - waiting for AsyncMethods 
2015-10-16 09:16:26,236 [main] DEBUG test.springAsync.TestAsyncBean - waiting for AsyncMethods 
2015-10-16 09:16:27,236 [main] DEBUG test.springAsync.TestAsyncBean - waiting for AsyncMethods 
2015-10-16 09:16:28,236 [main] DEBUG test.springAsync.TestAsyncBean - waiting for AsyncMethods 
2015-10-16 09:16:29,236 [main] DEBUG test.springAsync.TestAsyncBean - waiting for AsyncMethods 
2015-10-16 09:16:29,298 [testExecutor2] DEBUG test.springAsync.ProjectRepository - generateData end 
2015-10-16 09:16:29,298 [testExecutor1] DEBUG test.springAsync.ProjectRepository - generateData end 
2015-10-16 09:16:30,236 [main] DEBUG test.springAsync.TestAsyncBean - waiting for AsyncMethods 
2015-10-16 09:16:30,236 [main] DEBUG test.springAsync.TestAsyncBean - AsyncMethods did the job 

如您所见,两个日志线程启动并并行运行,大约11秒后终止。我建议您在代码中添加一些日志,并从命令行创建一个可运行的示例,以便轻松诊断问题所在

您是否可以尝试用Thread.sleep(10000)替换这个.generateData(),并告诉我们发生了什么?如果generateData()是cpu绑定的,并且线程被分配到同一个核心,那么即使两个任务异步运行,总时间也可能是20秒。我添加了generateData()方法,其中包含睡眠。您还需要其他信息吗?请将代码推送到github好吗?这样就更容易玩了。在我看来,如果您使用CompletableFuture,它的可读性会更高。我将推送到GitHub,您是对的,它会更容易!:)Url添加到原始帖子,但这里也是,谢谢是的,对不起,这是我的复制/粘贴错误,因为我部分是通过更改某些内容。我检查并返回
taskExecutor
@EddieJaoude我用一个可从命令行或IDE内部运行的工作示例重写了我的答案,谢谢!我将有一个剧本:)我在我的spring boot项目中尝试了同样的方法。但它不起作用。我需要为异步方法创建单独的类吗?我从未使用过Spring boot,所以我不确定,但我的示例仅依赖于Spring,即使它“嵌入”到Spring boot中,它也应该可以工作。您是尝试了我的示例还是创建了一些自定义代码?
package test.springAsync;

import java.util.List;
import java.util.concurrent.Future;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;

@Service
public class ProjectService {


    @Autowired
    private ProjectRepository projectRepository;

    @Async("taskExecutor1")
    public Future<List<Project>> getLatest() {
        return new AsyncResult<List<Project>>(this.projectRepository.getLatest());
    }

    @Async("taskExecutor1")
    public Future<List<Project>> getPopular() {
        return new AsyncResult<List<Project>>(this.projectRepository.getPopular());
    }
}
package test.springAsync;

import java.util.List;
import java.util.concurrent.Future;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class TestAsyncBean {
    private Logger logger=LoggerFactory.getLogger(TestAsyncBean.class.getName());
    @Autowired
    private ProjectService projectService;
    public void home() {
        logger.debug("start Home");
        Future<List<Project>> latest = projectService.getLatest();
        Future<List<Project>> popular = projectService.getPopular();

        try {
            while (!(latest.isDone() && popular.isDone())) {
                Thread.sleep(1000); //10-millisecond pause between each check
                logger.debug("waiting for AsyncMethods");
            }
            logger.debug("AsyncMethods did the job");
        } catch(Exception e) {
            System.out.println("ERROR in async thread " + e.getMessage());
        }

     }
}
package test.springAsync;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class TestMain {

    public static void main(String[] args) {
        ApplicationContext ctx = new AnnotationConfigApplicationContext(AsyncConfig.class);
        TestAsyncBean myService = ctx.getBean(TestAsyncBean.class);
        myService.home();

    }

}
2015-10-16 09:16:19,231 [main] DEBUG test.springAsync.TestAsyncBean - start Home 
2015-10-16 09:16:19,244 [testExecutor1] DEBUG test.springAsync.ProjectRepository - generateData start 
2015-10-16 09:16:19,244 [testExecutor2] DEBUG test.springAsync.ProjectRepository - generateData start 
2015-10-16 09:16:20,236 [main] DEBUG test.springAsync.TestAsyncBean - waiting for AsyncMethods 
2015-10-16 09:16:21,236 [main] DEBUG test.springAsync.TestAsyncBean - waiting for AsyncMethods 
2015-10-16 09:16:22,236 [main] DEBUG test.springAsync.TestAsyncBean - waiting for AsyncMethods 
2015-10-16 09:16:23,236 [main] DEBUG test.springAsync.TestAsyncBean - waiting for AsyncMethods 
2015-10-16 09:16:24,236 [main] DEBUG test.springAsync.TestAsyncBean - waiting for AsyncMethods 
2015-10-16 09:16:25,236 [main] DEBUG test.springAsync.TestAsyncBean - waiting for AsyncMethods 
2015-10-16 09:16:26,236 [main] DEBUG test.springAsync.TestAsyncBean - waiting for AsyncMethods 
2015-10-16 09:16:27,236 [main] DEBUG test.springAsync.TestAsyncBean - waiting for AsyncMethods 
2015-10-16 09:16:28,236 [main] DEBUG test.springAsync.TestAsyncBean - waiting for AsyncMethods 
2015-10-16 09:16:29,236 [main] DEBUG test.springAsync.TestAsyncBean - waiting for AsyncMethods 
2015-10-16 09:16:29,298 [testExecutor2] DEBUG test.springAsync.ProjectRepository - generateData end 
2015-10-16 09:16:29,298 [testExecutor1] DEBUG test.springAsync.ProjectRepository - generateData end 
2015-10-16 09:16:30,236 [main] DEBUG test.springAsync.TestAsyncBean - waiting for AsyncMethods 
2015-10-16 09:16:30,236 [main] DEBUG test.springAsync.TestAsyncBean - AsyncMethods did the job