2012-05-09 4 views
1

Я закодировал службу для создания эскизов изображений, динамически загружаемых пользователями на моем сайте. Это так, как это работает:Синхронизировать доступ к ресурсам в Java (Spring MVC)

Получить эскиз:

  1. имеет Проверить ли запрошенный этот эскиз до того
  2. Если нет, то изменение размера исходного изображения до требуемого размера и кэшировать его на жестком диске
  3. Возвращает кэшированные эскиз на жестком диске

Загрузить другое изображение:

  1. Проверьте, загружено ли это изображение раньше (например, пользователь может обновлять свой профайл, старый можно удалить)
  2. Если да, то удалите все эскизы старого изображения
  3. Сохранить/перезаписать новый загруженное изображение

Проблема заключается в пункт 2., когда пользователь запрашивает миниатюру. Что делать, если два пользователя запрашивают один и тот же эскиз в одно и то же время и не были изменены ранее? Оба запроса скажут серверу об изменении размера исходного изображения и сохранении его на жестком диске. Оба запроса будут пытаться записать один и тот же файл на жестком диске одновременно, что вызовет очевидные проблемы с доступом.

Как я могу избежать этого конфликта весной MVC? Вся эта логика эскиз управляется внутри контроллера Spring так:

@RequestMapping("/images/{width:\\d{1,10}}x{height:\\d{1,10}}/{subject:.+}.{ext:png|gif|jpg|PNG|GIF|JPG}") 
public void thumbnail(HttpServletResponse response, 
        HttpServletRequest request, 
        @PathVariable("width") int width, 
        @PathVariable("height") int height, 
        @PathVariable("subject") String subject, 
        @PathVariable("ext") String ext) throws IOException 
{ 
    // ... 
} 
+0

Можете ли вы опубликовать служебный код? Это звучит как простая проблема синхронизации? – MikePatel

ответ

1
  • Проверка на существование файла.

  • Если файл не существует:

    • создать ReentrantLock, и хранить его в ConcurrentHashMap с пути файла в качестве ключа, используя метод putIfAbsent().

    • Если putIfAbsent() возвращает замок, используйте следующую блокировку. В противном случае используйте созданный замок и сохраните его на карте.

    • Приобретите замок на ReentrantLock.

    • Как только у вас есть блокировка, проверьте, существует ли файл. Если это не так, создайте его. Иначе вам нечего делать, потому что параллельный поток создал его раньше.

    • Отпустите замок и удалите его с карты (в блок finally).

  • Прочтите файл и верните его содержимое.

Смежные вопросы