要求
我需要能够通过 POST 调用触发(长时间运行的)作业并立即返回。
一次只能有一个线程运行作业。
这项工作是一项昂贵的工作,如果一项工作已经在进行中,我希望这项工作的所有 future 触发器都不做任何事情。
代码
@RestController
public class SomeTask {
private SomeService someService;
@Autowired
public SomeTask(SomeService someService) {
this.someService = someService;
}
@Async // requirement 1
@RequestMapping(method = RequestMethod.POST, path = "/triggerJob")
public void triggerJob() {
expensiveLongRunningJob();
}
/**
* Synchronized in order to restrict multiple invocations. // requirement 2
*
*/
private synchronized void expensiveLongRunningJob() {
someService.executedJob();
}
}
问题
通过上述代码,满足了要求 1 和 2。满足要求 3 的最佳方法是什么(让作为 POST 调用的结果创建的新线程跳过同步方法并在获取锁失败时立即返回)?
最佳答案
同步不是完成这项工作的正确工具。你可以这样做:
@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();
}
}
关于Java:如果另一个线程已经在其中,则新线程将跳过同步方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56776981/