10 ottobre 2008

Eseguire un unica istanza di un'applicazione Java

Tempo fa mi sono imbattuto nel dilemma su come gestire in Java l'esecuzione di una sola istanza di una determinata applicazione, la rete mi è stata d'aiuto proponendomi una serie di soluzioni.
Una soluzione trovata è quella di recuperare tale informazione dall'elenco dei Thread in esecuzione, ma a parer mio è la peggiore.

Un altra soluzione è quella di istanziare un Server Socket su una determinata porta nel main dell'applicazione, nel caso in cui tale porta sia stata già Bindata, significa che si tratta della seconda istanza della stessa applicazione.

Una terza la soluzione, la migliore a pare mio è quella Unix Like in cui si esegue il lock su di un file durante l'esecuzione e sbloccare il lock al termine della stessa.

Di seguito l'esempio sul mio esempio di implementazione :

public class JustOneLock {
    private String appName;
    private File file;
    private FileChannel channel;
    private FileLock lock;

    public JustOneLock(String appName) {
        this.appName = appName;
    }

    public boolean isAppActive() {
        try {
            file = new File(System.getProperty("user.home"), appName + ".tmp");
            channel = new RandomAccessFile(file, "rw").getChannel();
            try {
                lock = channel.tryLock();
            } catch (OverlappingFileLockException e) {
                // il file è già loccato
                closeLock();
                return true;
            }

            if (lock == null) {
                closeLock();
                return true;
            }

            Runtime.getRuntime().addShutdownHook(new Thread() {
                    // distrugge il lock quando la JVM viene chiusa
                    public void run() {
                        closeLock();
                        deleteFile();
                    }
                });
            return false;
        }
        catch (Exception e) {
            closeLock();
            return true;
        }
    }

    // metodo per chiudere il lock sul file
    private void closeLock() {
        try { 
            lock.release();  
        }catch (Exception e) {  
            
        }
        try { 
            channel.close(); 
        }
        catch (Exception e) {  
        }
    }
    
    // metodo per cancellare il file di lock
    private void deleteFile() {
        try { 
            file.delete(); 
        }
        catch (Exception e) { 
        }
    }
}


Vediamo ora come utilizzare tale classe :
JustOneLock ua = new JustOneLock("JustOneId");
 
if (ua.isAppActive()) {
    System.out.println("Applicazione già in esecuzione. ");
}else {
    // caso in cui si tratta della prima istanza dell'applicazione
        System.out.println("Applicazione eseguita");
}

Spero che questo esempio sia stato utile. Alla prossima

2 commenti:

pier_IP ha detto...

Grazie mi e' stato molto utile :)

Anonimo ha detto...

Grazie, articolo utile!! Mi ha evitato lunghe ricerche sul web...