【问题标题】:@Async method inside synchronized method Java同步方法Java中的@Async方法
【发布时间】:2022-01-26 12:27:07
【问题描述】:

为了总结这个问题,我试图在同步方法中调用一些用@async 注释的方法。使用@async 的原因是因为我希望返回 post 方法的响应(以减少客户端的等待时间)并继续做一些后期处理工作(重置某些属性)。但是,由于 POST 方法涉及更改图形数据库,因此我使用 synchronized 关键字声明该方法,以防止在进行另一次计算时更改图形数据库。这样的结果似乎是两个线程都进入了同步方法,这不应该发生?

@RestController
public class Controller {

@PostMapping(path = “/compute”)
public synchronized String compute() {

System.out.println(“===== > In thread: “ + Thread.currentThread().getName());

System.out.print(“===== > Doing some work in compute”);

ResetService.reset()
Return(“===== > done computing”)
}


@Service
public class ResetService {@Async public void reset (){

System.out.println(“===== > resetting in thread: “ + Thread.currentThread().getName());
#(resetting some properties in neo4j graph database)
resetMethod();
System.out.print(“===== > Done Resetting”);
}

这会给我一个类似于这样的输出:

===== > 在线程中:http-nio-10080-exec-2

===== > 做一些计算工作

===== > 完成计算

=====> 在线程中重置:Async-1

===== > 在线程中:http-nio-10080-exec-3

===== > 做一些计算工作

===== > 完成重置

我对Synchronized方法的理解是,它只允许单个线程随时进入该方法。但似乎有两个线程同时运行同步计算方法。我试图为此想出一些原因,我能想到的两个主要原因是:

  1. 由于 Controller 类的实例不同,但我记得在某处读到 RESTController 默认情况下是单例范围,所以不应该是因为这个?

  2. 上下文切换?同步方法是否允许从一个线程到另一个线程的上下文切换?

如果我的问题的任何部分令人困惑,我深表歉意,因为我对 Java Spring/Spring Boot 相对较新,尤其是并发、多线程等概念。如果您需要我澄清我的问题的任何部分,请告诉我。

【问题讨论】:

    标签: java multithreading


    【解决方案1】:

    当您在同步方法compute() 中调用异步方法reset() 时,后一种方法不会等待reset() 完成。相反,它将生成一个新线程来处理reset() 的代码执行,然后立即进入下一行Return(“===== > done computing”)。之后,该方法将完成。当它完成时,一个新线程将被允许调用compute(),即使之前进入compute()的线程的reset()调用仍在单独的线程中运行。

    所以更清楚一点,方法compute() 不是两个线程同时进入的。之所以看起来如此,是因为来自线程http-nio-10080-exec-3 的部分文本打印在线程Async-1Done Resetting 打印之前。所以你的代码按预期工作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-06-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-10
      • 2011-11-08
      • 1970-01-01
      相关资源
      最近更新 更多