2014-09-06 61 views
0

我在Tomcat内部运行Java Web服务。防止Java Web服务发生同步修改记录

该服务被几个Rails应用程序使用,这些应用程序应该协调并发修改,但是做得不好。

只有一种感兴趣的服务方法,它尝试PUT一个用户记录,但它做了很多处理并且可能需要一段时间。这些Rails应用程序中的多个应用程序将尝试将更改推送给同一用户,而前一个调用仍在处理中的可能性很大。

我对Tomcat的单线程每请求的理解是,我真的在处理多线程问题,而不是在服务对象上同步,我想以某种方式同步临时用户标识。

我想过使用Set来存储当前处理的用户ID,然后在集合的对象上进行同步。第一个能够将用户标识添加到集合的过程中,而发现集合中已存在的用户标识的那个标识返回,例如409冲突错误。

Set<String> activeUserIds = new HashSet<String>(); 

// annotations, mappings, etc. 
public ResponseEntity<String> putUser(User user) { 

    boolean canProcess; 
    synchoronize(activeUserIds) { 
     canProcess = activeUserIds.add(user.getId()) { 
    } 

    if (!canProcess) { 
     return new ResponseEntity<String>("user already being modified", Status.CONFLICT); 
    } 

    // perform service activity 

    synchoronize(activeUserIds) { 
     activeUserIds.remove(user.getId()) { 
    } 

} 

这听起来可行吗?我还没有发现任何内置于Tomcat或Spring MVC中的内容,可以自动处理这种行为,但是是否已经有一个我不知道的内置解决方案?

+0

使用Java并发操作的任何解决方案(只)只能工作时,你的应用程序未跨多台机器/ JVM进行群集。你用什么后端存储用户记录?如果您正在使用SQL数据库,则可以在请求处理代码的开始处锁定该行。 – 2014-09-06 02:50:43

回答

0

我认为你提出的解决方案应该工作,只要你有一个webapp运行的实例(正如Erwin在注释中指出的那样)。我不知道任何内置的解决方案。

为了使代码更易于阅读,您也可以使用同步设置,摆脱两个​​声明:

Set<String> activeUserIds = Collections.synchronizedSet(new HashSet<String>());