The Spring application In the service spins an endless cycle
@Service
public class MyService {
public boolean isStart = false;
@Async("threadPoolTaskExecutor")
public void sending() {
while (isStartService) {
...
}
}
}
@Service
public class OneService {
@Autowired
private final MyService myService;
public void start(boolean isStautus) {
myService.isStart = true;
myService.sending();
}
}
In another service, I set the value of the variable is Start Service = true. While there was no Async annotation on this method, everything worked. But as soon as it was added, and it began to run in a separate thread, the isStartService variable inside this method is now always = false. The loop is never executed. How do I correctly pass the value of this variable inside this stream. I.e. at first it should be true, and after some time its value is passed false and thus the method stops working.
I tried to make the isStart variable as volatile. It didn't help
CodePudding user response:
The problem is that @Async
triggers the creation of a proxy
, so when you mutate the variable directly, the proxy doesn't intercept that call.
Create a setter
for the isStart
property and it'll work.
This application works as expected with the setter. You should make the field volatile
so that it always fetches the updated value of the field.
@SpringBootApplication
@EnableAsync
public class SO72313483 {
public static void main(String[] args) {
SpringApplication.run(SO72313483.class, args);
}
private final static Logger logger = LoggerFactory.getLogger(SO72313483.class);
@Service
public static class MyService {
private volatile boolean isStartService = false;
@Async("taskExecutor")
public void sending() throws Exception {
while (isStartService) {
logger.info("Here");
Thread.sleep(5000);
}
}
public void setStartService(boolean startService) {
isStartService = startService;
}
}
@Service
public static class OneService {
@Autowired
private MyService myService;
public void start(boolean isStatus) throws Exception{
myService.setStartService(true);
myService.sending();
}
}
@Autowired
OneService oneService;
@Bean
ApplicationRunner runnerSO72313483() {
return args -> oneService.start(true);
}
}