2012-03-22 6 views
1

私は、TCP接続を介して別のソフトウェア(たとえばS)を呼び出すJavaサーブレットを持っています。このソフトウェアSはネットワークリソースを使用し、出力はハイパーリンク(wgetを使用)から取得する必要があります。

リクエストとは無関係に結果をダウンロードする必要があるのは同じハイパーリンクなので、結果が間違った結果になります。私は基本的に、さまざまなプロセス間でこのネットワークリソースの使用をロックする必要があります(私はサーブレットからの各呼び出しが新しいプロセスを作成すると信じています)。

私は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

+0

通常の作業サーバーでは、各クライアント用のプロセスを作成しないでください。 –

答えて

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

+0

これは、ロックを取得するプロセスがまだアクティブである限り、動作します。そうでなければ、ロックは暗黙的に解放されたように見えます。つまり、プロセスがロックを手動で解放せずに「死んだ」場合、これは機能していないようです。 – searchengine27

0

なぜこのTCP接続を再利用していますか?セットアップが簡単な場合は、必要なときに毎回設定してください。たとえば、HTTPリクエストでは、毎回新しいリクエストを作成するだけです。

私は、staticがあるべきではないはずなので、複数のスレッドがすべて独自のバージョンを持つ必要がある場合は、そのスレッドを使用していると思います。

高価な場合は、ThreadLocalでスレッドごとに作成することを検討してください。

これでもうまくいかず、スレッドがブロックされても構わない場合は、問題の原因となっているメソッドに「synchronized」を追加してください。

0

ロックしようとしているリソースが見た目をサポートしている必要があります。サービスが外部的にロックされる必要がない場合は、より良いでしょう。

回避策として、ServerSocketを使用してプロセス間でリソースをロックすることができます。

関連する問題