Обработка одновременных HTTP-вызовов Spring Rest Controller - PullRequest
0 голосов
/ 09 июля 2020

Я пытаюсь принимать одновременные вызовы этого контроллера от клиента. Клиент пытается отправить фрагменты одного файла, а сервер пытается сначала собрать все эти фрагменты в массиве MultipartFile, а затем выполнить повторную сборку после получения всех фрагментов. Однако я не знаю, является ли этот код потокобезопасным, поскольку у меня есть общий ресурс, например массив файлов. Я создаю это при получении первого чанка. Я смущен, потому что этот код работает интересным образом. Например, он входит в оператор (file == null) 4-5 раз. Буду признателен, если кто-нибудь поможет сделать этот код без сохранения состояния или потокобезопасным!

@PostMapping("/mtupload/chunk")
public ResponseEntity<String> getMultithreadedUpload(@RequestParam("fileName") String fileName,
                                             @RequestParam("fileSize") String fileSize,
                                             @RequestParam("chunkSize") String chunkSize,
                                             @RequestParam("numberOfChunks") String numberOfChunks,
                                             @RequestParam("chunk") MultipartFile chunk,
                                             @RequestParam("chunkId") String chunkId,
                                             @RequestParam("fileId") String fileID) throws IOException {

    int chunkkSize = Integer.parseInt(chunkSize);
    int fileeSize = Integer.parseInt(fileSize);
    int chunkkId = Integer.parseInt(chunkId);
    int numberOfChunkss = Integer.parseInt(numberOfChunks);
    int fileIdd = Integer.parseInt(fileID);

    if(file == null)
    {
        System.out.println("Server created array of length " + numberOfChunkss + " Inside chunk " + chunkId);
        
        //static MultipartFile[] file is defined as global variable
        file = new MultipartFile[numberOfChunkss];
    }
    if(chunk.getSize() == 0)
    {
        return new ResponseEntity<>(" Server failed to get chunk "+ chunkId + " !", HttpStatus.INTERNAL_SERVER_ERROR);
    }

    System.out.println("Server got chunk " + chunkId );

    file[chunkkId] = chunk;
    System.out.println("Chunk size in File " + chunkId  + " : " + file[chunkkId].getSize());

    // call to store the file when all chunks are received.
    //        storageService.storeChunks(file, fileName, numberOfChunkss, chunkkSize);
    return new ResponseEntity<>(" Server got chunk "+ chunkId + " !", HttpStatus.OK);
}

1 Ответ

0 голосов
/ 09 июля 2020

Код не является потокобезопасным. Это похоже на то, что более одного потока создадут новый file. Вы можете объявить файл изменчивым и добавить синхронизацию к блоку нулевой проверки:

if(file==null) {
  synchronized(this) {
    if(file==null) {
    ...
    }
  }
}

Предполагая, что идентификаторы блоков уникальны, полученный код будет потокобезопасным.

...