我在這裏看到了一些類似的問題,但是他們的解決方案都沒有工作。我的2個異步調用同步運行。Spring Boot @Async同步運行
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();
}
}
服務都從控制器呼籲應採取大約10秒鐘,如果運行的異步,但它仍然需要20秒 - 我失去了什麼?
PS。忽略簡單的愚蠢,沒有接口等,我儘可能地去除了嘗試和隔離問題。我原本跟着官方的文檔https://spring.io/guides/gs/async-method/
代碼在GitHub上:https://github.com/DashboardHub/PipelineDashboard/tree/feature/homepage
你可以嘗試用Thread.sleep(10000)代替this.generateData()並告訴我們會發生什麼?如果generateData()被CPU綁定,並且線程被分配到相同的核心,則即使兩個任務運行異步,總時間可能也是20秒。 – Giovanni
我已經添加了包含睡眠的我的generateData()方法。您需要的任何其他信息? –
你能把這個代碼推到github上嗎?所以玩起來會更容易。如果你使用CompletableFuture,它會更具可讀性 – freakman