FileChannel & RandomAccessFile non sembrano funzionare
Domanda
Per dirla semplice: un'applicazione swing che utilizza sqlitejdbc come backend. Attualmente, non c'è nessun problema di lanciare più istanze che lavorano con lo stesso file di database. E ci dovrebbe essere. Il file è bloccato (non in grado di eliminarlo mentre l'applicazione è in esecuzione) in modo che il controllo dovrebbe essere banale. Si scopre che non.
File f = new File("/path/to/file/db.sqlite");
FileChannel channel = new RandomAccessFile(f, "rw").getChannel();
System.out.println(channel.isOpen());
System.out.println(channel.tryLock());
risultati in
true
sun.nio.ch.FileLockImpl[0:9223372036854775807 exclusive valid]
Non importa se l'applicazione è in esecuzione o meno. Mi sto perdendo il punto? TIA.
Soluzione
FileLocks sono esclusivi a JVM, non un singolo filo. Quindi, se è stato eseguito il codice all'interno dello stesso processo come il vostro swing app, si otterrebbe il blocco perché è condiviso dalla JVM.
Se il vostro swing applicazione non è in esecuzione, nessun altro processo si contendono il blocco in modo da ottenere che non v'è bene.
Altri suggerimenti
un blocco di file a livello di sistema interagisce con altre applicazioni. È possibile ottenere uno di questi da FileChannel. Quindi, ciò che si fa nel codice di esempio renderà il file sembra bloccato a un altro processo, ad esempio vi.
Tuttavia, altri thread Java o processi all'interno della JVM non vedrà la serratura. La frase chiave è "blocchi dei file sono detenuti per conto di tutta la macchina virtuale Java. Essi non sono adatti per controllare l'accesso a un file da più thread all'interno della stessa macchina virtuale." non si è vedendo il bloccare, quindi si esegue sqlitejdbc all'interno della stessa JVM come applicazione.
Quindi la domanda è come si fa a vedere se il vostro JVM ha già acquisito un blocco su un file (supponendo che non controlli il codice di acquisire il blocco)? Un suggerimento che avrei è cercare di acquisire un blocco esclusivo su un diverso sottoinsieme di file, ad esempio con questo codice:
fc.tryLock(0L, 1L, false)
Se c'è già un blocco si dovrebbe ottenere un OverlappingFileLockException. Questo è un po 'hacky, ma potrebbe funzionare.
Si può fare un piccolo esperimento? Eseguire due copie di questo programma (basta il codice con un sonno):
public class Main {
public static void main(String [] args) throws Exception {
File f = new File("/path/to/file/db.sqlite");
FileChannel channel = new RandomAccessFile(f, "rw").getChannel();
System.out.println(channel.isOpen());
System.out.println(channel.tryLock());
Thread.sleep(60000);
}
}
Se questo non si blocca a sapere che tryLock () non funziona sul vostro OS / unità / JVM. Se questo non bloccare poi qualcosa è sbagliato con la vostra logica. Fateci sapere il risultato in un commento.