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

Leer datos de Firebase desde Android

En este post crearemos una aplicación en Android Studio para conectarnos con nuestra base de datos de Firebase y leer al[...]

Ejemplo de procesamiento por lotes con PHP

El procesamiento por lotes (batch processing) en PHP es la ejecución de tareas que implican una gran cantidad de datos u[...]

Conectar SQL Server con VB6

En este post, aprenderemos como conectar Visual Basic 6 con SQL Server, abrir una tabla, leer su contenido y mostrar est[...]

Microservicio REST Java con Spark – Parte 2

Segunda y ultima parte del post dedicado a la creación de un microservicio en lenguaje java utilizando el framework Spar[...]

Dimask: La mascara de la Belleza (Descargar)

La Belleza está en la Simetría ¿Qué es lo que nos hace considerar un rostro bello? ¿Está influenciado nuestro criterio p[...]

Convertir imagenes JPEG a video MOV

Googleando me encontré con una interesante clase java «JpegImagesToMovie» que convierte imágenes JPEG a vídeo MOV de[...]