我创建了一个REST控制器(在Spring Boot 2.2.2中),该控制器调用“ Invokable”服务类,如下所示:
@RestController
@RequestMapping("service")
public class ServiceController {
private Set<Invokable> services;
@Autowired
public ServiceController(Set<Invokable> services) {
this.services = services;
}
@GetMapping("invoke/{service}")
public void invoke(@PathVariable("service") String service) throws InterruptedException {
val invokable = services.stream().filter(c -> AopUtils.getTargetClass(c).getName().equals(service)).findFirst();
invokable.get().invoke();
}
}
所述Invokable
接口方法被标记Async
:
public interface Invokable {
@Async("taskExecutor")
void invoke();
}
其中一种实现如下所示:
@Service
@Transactional
public class EventListener implements Invokable {
private static boolean RUNNING = false;
private EventService eventService;
private List<EventProcessor> processors;
@Autowired
public EventListener(EventService eventService,
List<EventProcessor> processors) {
this.eventService = eventService;
this.processors = processors;
}
@Override
public void invoke() {
if (!RUNNING) {
RUNNING = true;
[...]
RUNNING = false;
}
}
}
在上面可以看到,我通过使用RUNNING
boolean 锁定方法来实现了自定义同步机制。这很好用,但是我不想自己实现。
之前,我曾尝试(通过lombok
):
@Override
@Synchronized
public void invoke() {
...
}
和
@Override
public synchronized void invoke() {
...
}
和
@Override
public void invoke() {
synchronized(this) {
...
}
}
但是,以上所有内容似乎允许同时调用该方法。
我想念过什么synchronized
用吗?是否有一种更清洁的方法可以实现上述目标而无需自己实施该机制?
synchronized
防止并发调用。但这并不意味着在运行时进行的调用将被丢弃并被忽略。这意味着它将阻塞,等待直到上一个完成,然后再执行。
您的代码不同步任何内容。它仅忽略运行时进行的调用,这是非常不同的。它以一种非线程安全的方式进行操作:同时调用该方法的两个独立线程可能会看到布尔值相同,并且都同时执行该方法。更糟糕的是:在一个线程中对布尔值所做的更改可能在另一个线程中不可见。
您将需要正确地使用AtomicBoolean以线程安全的方式执行操作。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句