简体   繁体   中英

How to make a synchronous rest controller in Spring boot?

I have a controller that I want to process requests synchronously. 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. If it does already exist then the "num" is not added, if it doesn't exist then it adds the "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?

@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.

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 . 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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