简体   繁体   English

在另一个线程中运行的方法中未读取服务变量

[英]The service variable is not read in a method running in another thread

The Spring application In the service spins an endless cycle Spring应用程序在服务中旋转着一个无休止的循环

@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.在另一个服务中,我设置变量的值为 Start Service = true。 While there was no Async annotation on this method, everything worked.虽然此方法没有 Async 注释,但一切正常。 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.但是一旦它被添加,并且它开始在一个单独的线程中运行,这个方法中的 isStartService 变量现在总是 = false。 The loop is never executed.循环永远不会执行。 How do I correctly pass the value of this variable inside this stream.如何在此流中正确传递此变量的值。 Ie 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.我试图将 isStart 变量设置为 volatile。 It didn't help它没有帮助

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.问题是@Async触发了proxy的创建,因此当您直接改变变量时,代理不会拦截该调用。

Create a setter for the isStart property and it'll work.isStart属性创建一个setter ,它将起作用。

This application works as expected with the setter.此应用程序与 setter 一起按预期工作。 You should make the field volatile so that it always fetches the updated value of the field.您应该使该字段volatile ,以便它始终获取该字段的更新值。

@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);
    }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM