2012-03-22 31 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在進程之間鎖定資源。