Aprende Java Aprende Php Aprende C++ Aprende HTML 5 Aprende JavaScript Aprende JSON Aprende MySQL Aprende SQLServer Aprende Visual Basic 6 Aprende PostgreSQL Aprende SQLite Aprende Redis Aprende Kotlin Aprende XML Aprende Linux VSC Aprende Wordpress Aprende Laravel Aprende VueJS Aprende JQuery Aprende Bootstrap Aprende Netbeans Aprende Android
Sigueme en Facebook Sigueme en Twitter Sigueme en Instagram Sigueme en Youtube Sigueme en TikTok Sigueme en Whatsapp
Home / Java / Proyectos / Evitar ejecutar un programa java más de una vez

Evitar ejecutar un programa java más de una vez

Por jc mouse jueves, febrero 21, 2013

Cuando se hace uso de programas a veces no importa que este cree más de una instancia al mismo tiempo, por ejemplo podemos ejecutar Paint varias veces y trabajar en paralelo en varios proyectos.

Un programa hecho en java puede ejecutarse las veces que sea al mismo tiempo con tan solo hacer doble clic en los archivos JAR, esto crea una nueva instancia de la aplicación que no es más que una copia exacta del programa en memoria.  Pero en ocasiones ya sea por X o Z motivos, se trata de evitar que esto suceda y maneras hay varias, yo te presento una de ellas, la más sencilla.

Explicación.

Para evitar que se creen más de una instancia a la vez de un ejecutable *.JAR, utilizaremos un archivo *.TMP (No confundir con archivos temporales creados con createTempFile ) en donde almacenaremos un valor LONG que corresponde  al tiempo actual en milisegundos  desde el 01 de enero de 1970, 00:00:00 GMT utilizando el método getTime() del objeto Date, el valor que se obtiene es de la forma «1361471591388».

El valor LONG obtenido se almacenara en un archivo *.TMP que se llamara «miApp.tmp«. Paralelamente se iniciara un proceso que cada cierto tiempo (20 segundos, 1 minuto, 5 minutos, etc) refrescará el valor de miApp.tmp con el tiempo actual en milisegundos, para esto se emplea el objeto «ScheduledExecutorService«.

Cuando se cree una nueva instancia del programa java, este primeramente verificara que el archivo miApp.tmp exista, si no existe, no existe una instancia del programa por tanto crea el archivo *.tmp e inicia la aplicación normalmente, si el archivo SI EXISTE, entonces supone que existe una instancia de la aplicación así que lee el valor del archivo *.tmp  y realiza una resta, el resultado de la resta dado en segundos  determinara si la instancia  del programa esta activo y por tanto no crea una nueva instancia del programa.

Cuando el programa java se cierra, se destruirá el archivo *.TMP

Si me entendieron hasta aquí, entonces una aclaración, :=D , ¿porqué actualizamos el valor del archivo miApp.tmp cada cierto tiempo?, porque puede ocurrir que el programa se cierre inesperadamente y NO se destruya el archivo temporal por tanto, cuando se trate de ejecutar el archivo *.jar, saldrá el aviso «El programa ya esta en ejecución»  hasta que el archivo tmp sea eliminado manualmente, para evitar esto, si el archivo TMP ya existe, solamente debemos restamos el valor que tiene y si el resultado es mayor al tiempo que asignamos para la actualización del archivo TMP, damos por hecho de que NO EXISTE UNA INSTANCIA de la aplicación así que creamos una.

Como parece chino lo que estoy diciendo 🙂 una imagen vale mas que mil palabras:

grafico cool

clic para ampliar

Implementamos el código en una sola clase que llamamos «Control.java»

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import javax.swing.JOptionPane;
/**
 * @web https://www.jc-mouse.net
 * @author Mouse
 */
public class Control {

    //fichero TMP
    private String appPath = System.getProperties().getProperty("user.dir");
    private File fichero = new File( appPath + "\\miApp.tmp");    
    //tiempo en que se actualiza el fichero TMP
    private int segundos = 20;

    /** Constructor de clase */
    public Control(){};

    /**
 * Comprueba que archivo TMP exista, sino lo crea e inicia valores
 */
    public boolean comprobar()
    {           
        if ( fichero.exists() )
        {           
            long tiempo = leer();//
            long res = restarTiempo( tiempo );           
            if( res < segundos )
            {              
                JOptionPane.showMessageDialog(null,"Error: La aplicacion ya esta en ejecución.");
                return false;
            }
            else
            {        
                programar_tarea();
                return true;
            }
        }
        else// no existe fichero
        {
            crearTMP();   
            programar_tarea();
            return true;
        }            
    }

    /**
 * Lee el archivo TMP y retorna su valor 
 * @return LONG cantidad de milisegundos 
 */
    public long leer()
    {
        String linea = "0";        
        BufferedReader bufferedReader;
        try {
            bufferedReader = new BufferedReader( new FileReader( fichero ) );            
            while(bufferedReader.ready()){
                linea = bufferedReader.readLine();            
        }
        }catch (IOException e) {
            System.err.println( e.getMessage() );
        }
        return Long.valueOf(linea).longValue();
    }

    /**
 * Programa un proceso que se repite cada cierto tiempo
 */
    public void programar_tarea()
    {
        ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
        scheduler.scheduleAtFixedRate( 
            new Runnable() 
            {
                @Override
                public void run() {                   
                    crearTMP(); 
                }
              }, 1000, segundos * 1000 , TimeUnit.MILLISECONDS ); //comienza dentro de 1 segundo y luego se repite cada N segundos

    }

    /**
 * Crea un archivo TMP con un unico valor, el tiempo en milisegundos
 */
    public void crearTMP()
    {
        Date fecha=new Date();        
        try {            
            BufferedWriter writer = new BufferedWriter(new FileWriter( fichero ));                        
            writer.write(  String.valueOf( fecha.getTime() ) );                        
            writer.close();            
        } catch (IOException e) {
            System.err.println( e.getMessage() );
        }        
    }

    /**
 * Resta el tiempo expresado en milisegundos
 * @param tiempoActual el tiempo actual del sistema expresado en milisegundos
 * @return tiempo el resultado expresado en segundos
 */
    public long restarTiempo( long tiempoActual )
    {
        Date date =new Date();        
        long tiempoTMP = date.getTime();        
        long tiempo = tiempoTMP - tiempoActual;        
        tiempo = tiempo /1000;        
        return tiempo;
    }

    /**
 * Elimina el fichero TMP si es que existe
 */
    public void cerrarApp()
    {   
        if ( fichero.exists() ) { fichero.delete(); }
        System.exit(0);
    }

}//--> fin clase

 

Y para poder utilizar esta clase en nuestra aplicación, la implementamos en el MAIN

public class MiApp {

    public static void main(String[] args) {
        if( new Control().comprobar() )
        {
            new interfaz().setVisible( true );
        }        
        else
        {
            System.exit(0);
        }
    }
}

Para que al cerrar la aplicación se elimine el archivo TMP, se debe implementar el método cerrarApp() en la interfaz de nuestro programa, por ejemplo en un boton:

    private void btnCerrarActionPerformed(java.awt.event.ActionEvent evt) {
          new Control().cerrarApp();          
    }

Eso es todo

demo

Proyecto y ejemplo

Tags

Artículos similares

Reproduce archivos MP3 desde android

Reproducir archivos de audio en nuestras aplicaciones android. Necesitamos IDE Eclipse y SDK Android instalado Un archiv[...]

Recortar imagen

En esta oportunidad dejo a considerancion un codigo realizado en Java/Netbeans para recortar una imagen visualmente Vide[...]

Procedimientos Almacenados: Parámetros INOUT

En post anteriores vimos lo que son los parámetros IN y los parámetros OUT pero existe otro tipo de parámetro que es la[...]

Generación de laberintos: Algoritmo de Aldous-Broder

El Algoritmo de Aldous-Broder llamado así por dos matemáticos, David Aldous and A. Broder (quienes trabajaban en la inve[...]

Números narcisistas o de Armstrong

Los números narcisistas o números de Armstrong son aquellos números enteros positivos  cuya suma de las n-ésim[...]

Potigol: Lenguaje de programación en portugues

Oi galera, en esta oportunidad les traigo una curiosidad que encontré por casualidad perdiendo el tiempo en Internet, se[...]