java - Java:如果另一个线程已经在其中,则新线程将跳过同步方法
问题描述
要求
我需要能够通过 POST 调用触发(长时间运行的)作业并立即返回。
一次只能有一个线程运行该作业。
这项工作是一项昂贵的工作,如果一项工作已经在进行中,我希望这项工作的所有未来触发器都不做任何事情。
代码
@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();
}
}
推荐阅读
- php - 如何使用 PHP 实现 OpenSSL 的 SSL_Write()
- python - 在文本或 json 文件中创建用户并将其用于登录 python 网络
- json - Angular4按过滤器分组不适用于管道:ngx-pipes
- python - 如何计算python数据框中的词频?
- c# - 在 UWP 中显示音频电平
- google-apps-script - 来自 Google Apps 脚本的 Spotify API 用户授权
- jenkins - 在本地开发环境条件下跳过 Jenkins 管道阶段
- spock - 如何设置可重用的 Geb 测试脚本(供其他测试脚本使用)
- javascript - How to disable wait for page loading in ProTractor
- f# - Project with generated types fails on Assembly.GetExportedTypes()