2012-03-22 59 views
1

我有一个Java servlet,它通过TCP连接调用另一个软件(比如S)。该软件S使用网络资源,并且输出必须从超链接中检索(使用wget)。

由于它是我需要从(无论请求)下载我的结果相同的超链接,它会导致不正确的结果几个请求。我基本上需要在不同进程间锁定这个网络资源的使用(我相信每个来自servlet的调用都会创建一个新进程)。

我试图使用ReentrantLock(但我想它只适用于线程而不是跨进程)。

请让我知道这是如何实现的。用Java锁定进程

谢谢

+0

如果他们在同一个容器中运行,并调用到相同的资源,可以考虑使用['synchronized'(http://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth。 HTML)。请注意,这适用于_threads_。对于进程,如上所示,看看[这里](http://stackoverflow.com/questions/5297813/cross-process-synchronization-in-java)。 – MrGomez 2012-03-22 21:32:21

+0

正常工作的服务器不应该为每个客户端创建一个进程。 – 2012-03-22 21:35:53

回答

2

以下是如何在Java中进行跨进程锁定。根据需要调整并根据需要添加错误/异常检查/处理。

// Tester 
try { 
    if (crossProcessLockAcquire(SomeClassInYourApp.class, 3000)) { 
    // Success - This process now has the lock. (Don't keep it too long.) 
    } 
    else { 
    // Fail (Timeout) - Another process still had the lock after 3 seconds. 
    } 
} finally { 
    crossProcessLockRelease(); // try/finally is very important. 
} 

// Acquire - Returns success (true/false) 
private static boolean crossProcessLockAcquire(final Class<?> c, final long waitMS) { 
if (fileLock == null && c != null && waitMS > 0) { 
    try { 
     long dropDeadTime = System.currentTimeMillis() + waitMS; 
     File file = new File(lockTempDir, c.getName() + ".lock"); 
     RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw"); 
     FileChannel fileChannel = randomAccessFile.getChannel(); 
     while (System.currentTimeMillis() < dropDeadTime) { 
      fileLock = fileChannel.tryLock(); 
      if (fileLock != null) { 
       break; 
      } 
      Thread.sleep(250); // 4 attempts/sec 
     } 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 
return fileLock == null ? false : true; 
} 

// Release 
private static void crossProcessLockRelease() { 
if (fileLock != null) { 
    try { 
     fileLock.release(); 
     fileLock = null; 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
} 
} 

// Some class vars and a failsafe lock release. 
private static File lockTempDir = new File(System.getProperty("java.io.tmpdir") + File.separator + "locks"); 
private static FileLock fileLock = null; 
static { 
Runtime.getRuntime().addShutdownHook(new Thread() { 
    public void run(){ 
     crossProcessLockRelease(); 
    } 
}); 
}  
+0

谢谢。这应该适用于我:) – Leo 2012-03-24 22:24:38

+0

只有在获取锁的进程仍处于活动状态时,这才起作用。如果没有,锁似乎隐含释放。换句话说,如果一个进程“死亡”而没有手动释放锁,这似乎不起作用。 – searchengine27 2015-08-24 20:51:40

0

你为什么重复使用这个TCP连接?如果设置起来很简单,只需在每次需要时设置一个即可。例如,对于HTTP请求,您应该每次都提出一个新请求。

我的猜测是你有static不应该这样,所以多个线程都应该使用它,当他们都应该有自己的版本。

如果价格昂贵,请考虑使用ThreadLocal创建一个每线程。

如果即使这不起作用,并且您不介意线程阻塞,只需将“synchronized”添加到导致问题的方法即可。

0

您试图锁定的资源必须支持查找。如果服务不需要被外部锁定,那会更好。

作为解决方案,您可以使用ServerSocket在进程之间锁定资源。