简体   繁体   English

如何在 Spring 引导中制作同步 rest controller?

[英]How to make a synchronous rest controller in Spring boot?

I have a controller that I want to process requests synchronously.我有一个 controller 我想同步处理请求。 If multiple requests come in for this method at the exact same time I want the method to be synchronized and process them one by one and not concurrently.如果该方法同时收到多个请求,我希望该方法同步并一个一个地处理它们,而不是同时处理它们。

The add method receives a "num" and checks the nums list to see if "num" exists in the list. add 方法接收一个“num”并检查 nums 列表以查看列表中是否存在“num”。 If it does already exist then the "num" is not added, if it doesn't exist then it adds the "num".如果已经存在,则不添加“num”,如果不存在,则添加“num”。 I want to make this method synchronized so that if two add requests come in with the same number at the same time the first request will execute and return "number added" and the second one will return "number not added".我想让这个方法同步,这样如果两个添加请求同时带有相同的数字,第一个请求将执行并返回“添加的数字”,第二个请求将返回“未添加的数字”。 How would I do this?我该怎么做? with the java "synchronized" keyword?使用 java“同步”关键字?

@RestController
@RequestMapping(path="/numberList")
public class ListController {
   
   @PostMapping("/add")
   public String add(@RequestParam(name="num", required=true)int num) {
      boolean matches = false;
      ​
      ​for(int i : RuntimeMetrics.getNums()) {
         if(i.equals(num) {
            matches = true;
         }            
      ​}
      
      if(matches) {
         return "number not added";
      }
      else{
         RuntimeMetrics.getNums().add(num);
         return "number added";
      }      
   }
}
public class RuntimeMetrics {
   private static ArrayList<Integer> nums = new ArrayList<Integer>();
  ​
   ​public static ArrayList<Integer> getNums(){
      ​return nums;
   ​}
}

Your current implementation is very un-atomic.您当前的实现非常非原子。 The for -loop could deliver false for two or even more requests with the same number. for循环可以为两个甚至更多具有相同数量的请求提供false

The simplest approach would be to add some sort of concurrent data structure allowing access control to your list.最简单的方法是添加某种并发数据结构,允许对您的列表进行访问控制。

@RestController
@RequestMapping(path="/numberList")
public class ListController {
   private static final Set<Integer> ADDED_NUMBERS = ConcurrentHashMap.newKeySet(); // concurrent set implementation in Java

   @PostMapping("/add")
   public String add(@RequestParam(name="num", required=true) final int num) {
      if(ADDED_NUMBERS.add(num)) {
         RuntimeMetrics.getNums().add(num);
         return "number added";
      }
      else {
         return "number not added";
      }      
   }
}

The concurrent Set implementation ensures an atomic add .并发Set实现确保原子add Even if there are hundred simultaneous requests with the same number only one would return "number added".即使有数百个具有相同编号的同时请求,也只有一个会返回“添加的编号”。

A classic synchronous approach to the list would be possible but far less efficient and very single-threaded.一种经典的列表synchronous方法是可能的,但效率要低得多,而且非常单线程。

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

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