2012-03-22 3 views
1

J'ai une servlet Java qui appelle un autre logiciel (disons S) via une connexion TCP. Ce logiciel S utilise une ressource réseau et la sortie doit être récupérée à partir d'un lien hypertexte (en utilisant wget).

Comme c'est le même lien hypertexte dont j'ai besoin de télécharger mon résultat (indépendamment de la demande), il en résulte des résultats incorrects quelques demandes. J'ai fondamentalement besoin de verrouiller l'utilisation de cette ressource réseau à travers différents processus (je crois que chaque appel de la servlet va créer un nouveau processus).

J'ai essayé d'utiliser ReentrantLock (mais je suppose que cela ne fonctionne qu'avec les threads et pas les processus).

S'il vous plaît laissez-moi savoir comment cela peut-il être atteint.Verrouillage d'un processus en Java

Merci

+0

Si elles sont en cours d'exécution dans le même récipient et remettre en la même ressource, pensez à utiliser [ 'synchronized'] (http://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth. html). Notez que ceci est applicable à _threads_. Pour les processus, comme ci-dessus, regardez [ici] (http://stackoverflow.com/questions/5297813/cross-process-synchronization-in-java). – MrGomez

+0

Un serveur de travail normal ne doit pas créer de processus pour chaque client. –

Répondre

2

Voici comment procéder au verrouillage inter-processus en Java. Ajustez à vos besoins et ajoutez l'erreur/le contrôle/la gestion d'exception si nécessaire.

// 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

Merci. Cela devrait fonctionner pour moi :) – Leo

+0

Cela ne fonctionne que tant que les processus qui obtiennent le verrou sont toujours actifs. Sinon, le verrou semble être libéré implicitement. En d'autres termes, si un processus "est mort" sans relâcher manuellement le verrou, cela ne semble pas fonctionner. – searchengine27

0

Pourquoi réutilisez-vous cette connexion TCP? Si c'est facile à configurer, installez-en un chaque fois que vous en avez besoin. Par exemple, avec une requête HTTP, vous devriez simplement faire une nouvelle requête à chaque fois.

Je suppose que vous avez quelque chose qui ne devrait pas être le static, donc plusieurs threads l'utilisent alors qu'ils devraient tous avoir leur propre version.

Si elles sont chères, envisagez de créer un par thread avec ThreadLocal.

Si cela ne fonctionne pas, et que le blocage des threads ne vous dérange pas, ajoutez simplement "synchronized" à la méthode à l'origine du problème.

0

La ressource que vous essayez de verrouiller doit prendre en charge la recherche. Il serait préférable que le service n'ait pas besoin d'être verrouillé à l'extérieur. Pour contourner le problème, vous pouvez utiliser un serveur ServerSocket pour verrouiller une ressource entre les processus.

Questions connexes