gpt4 book ai didi

java - Spring Boot @Async 同步运行

转载 作者:行者123 更新时间:2023-11-30 07:52:30 26 4
gpt4 key购买 nike

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

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";
}
}

ProjectService.java

@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());
}

ProjectRepository.java

@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;
}
}

AsyncConfig.java

@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();
}
}

如果运行异步,来自 Controller 的两个服务调用大约需要 10 秒,但仍然需要 20 秒 - 我错过了什么?

PS。忽略简单性和愚蠢性,没有接口(interface)等,我删除了尽可能多的内容以尝试隔离问题。我最初遵循官方文档 https://spring.io/guides/gs/async-method/

GitHub 上的代码:https://github.com/DashboardHub/PipelineDashboard/tree/feature/homepage

最佳答案

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

package test.springAsync;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.TaskExecutor;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

@Configuration
@ComponentScan(basePackages = "test.springAsync")
@EnableAsync
public class AsyncConfig {

private int poolSize=10;

private int queueCapacity=10;

@Bean(name = "taskExecutor1")
public TaskExecutor taskExecutor() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
taskExecutor.setCorePoolSize(10);
taskExecutor.setMaxPoolSize(this.poolSize);
taskExecutor.setQueueCapacity(this.queueCapacity);
taskExecutor.afterPropertiesSet();
taskExecutor.setThreadNamePrefix("testExecutor");
return taskExecutor;
}
}

项目类

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;
}
}

ProjectService 类:

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());
}
}

我将 TestAsyncBean 作为 Controller 的替代品:

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());
}

}
}

TestMain 是我用来将所有内容放在一起的类:

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();

}

}

最后这是 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

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

关于java - Spring Boot @Async 同步运行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33163503/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com