在Java中同步对资源的访问(Spring MVC)

时间:2012-05-09 10:22:03

标签: java spring spring-mvc

我编写了一项服务,为我网站上的用户动态上传的图片生成缩略图。这是它的工作方式:

获取缩略图:

  1. 之前检查是否已请求此缩略图
  2. 如果没有,请将原始图像调整为所需大小并将其缓存在硬盘驱动器上
  3. 返回缓存在硬盘上的缩略图
  4. 上传其他图片:

    1. 检查此图片之前是否已上传(例如,用户可能正在更新其个人资料图片,旧图片可以删除)
    2. 如果是,请删除旧图像的所有缩略图
    3. 保存/覆盖新上传的图片
    4. 问题出在第2点。当用户请求缩略图时。如果两个用户在同一时间请求相同的缩略图并且之前没有调整大小,该怎么办?这两个请求都会告诉服务器调整原始图片的大小并将其保存在硬盘上。 两个请求都会尝试同时在硬盘驱动器上写入相同的文件,从而导致明显的访问问题。

      如何在Spring 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
      {
          // ...
      }
      

1 个答案:

答案 0 :(得分:1)

  • 检查文件是否存在。

  • 如果文件不存在:

    • 创建一个ReentrantLock,并使用putIfAbsent()方法将文件路径作为键存储在ConcurrentHashMap中。

    • 如果putIfAbsent()返回锁定,请在下面使用此锁定。否则,请使用您创建并存储在地图中的锁。

    • 获取ReentrantLock上的锁。

    • 获得锁定后,请检查文件是否存在。如果没有,请创建它。否则,你没有任何事情可做,因为并发线程之前创建了它。

    • 释放锁并将其从地图中移除(在最后一个区块中)。

  • 阅读文件并返回其内容。