2 回答

TA貢獻1784條經驗 獲得超7個贊
同步不是完成這項工作的正確工具。你可以這樣做:
@RestController
public class SomeTask {
private SomeService someService;
private final AtomicBoolean isTriggered = new AtomicBoolean();
@Autowired
public SomeTask(SomeService someService) {
this.someService = someService;
}
@Async // requirement 1
@RequestMapping(method = RequestMethod.POST, path = "/triggerJob")
public void triggerJob() {
if (!isTriggered.getAndSet(true)) {
try {
expensiveLongRunningJob();
} finally {
isTriggered.set(false);
}
}
}
/**
* only runs once at a time, in the thread that sets isTriggered to true
*/
private void expensiveLongRunningJob() {
someService.executedJob();
}
}

TA貢獻1871條經驗 獲得超8個贊
對于要求 1,如果你只想使用@Async,你應該在服務方法而不是控制器方法上使用它。但請注意,通過使其異步,您將失去對作業的控制,并且無法進行故障處理,除非您通過實現接口來實現@Async和Future處理故障AsyncUncaughtExceptionHandler。
對于要求 3,您可以在服務中有一個 volatile 布爾字段,它在開始作業流程之前設置,并在作業流程完成后取消設置。在您的控制器方法中,您可以檢查服務的易失性布爾字段以確定作業是否正在執行,如果作業正在進行則返回適當的消息。另外,確保在處理AsyncUncaughtExceptionHandler接口實現失敗時取消設置布爾字段。
服務:
@Service
public class SomeService {
public volatile boolean isJobInProgress = false;
@Async
public Future<String> executeJob() {
isJobInProgress = true;
//Job processing logic
isJobInProgress = false;
}
}
控制器:
@RestController
public class SomeTask {
@Autowired
private SomeService someService;
@RequestMapping(method = RequestMethod.POST, path = "/triggerJob")
public void triggerJob() {
if (!someService.isJobInProgress){
someService.executeJob(); //can have this in a sync block to be on the safer side.
} else {
return;
}
}
}
AsyncUncaughtExceptionHandler 的實現:
public class CustomAsyncExceptionHandler implements AsyncUncaughtExceptionHandler {
@Autowired
private SomeService someService;
@Override
public void handleUncaughtException(
Throwable throwable, Method method, Object... obj) {
//Handle failure
if (someService.isJobInProgress){
someService.isJobInProgress = false;
}
}
}
@異步配置:
@Configuration
@EnableAsync
public class SpringAsyncConfig implements AsyncConfigurer {
@Override
public Executor getAsyncExecutor() {
return new ThreadPoolTaskExecutor();
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new CustomAsyncExceptionHandler();
}
}
添加回答
舉報