Implementación de Patrón de Hilo Único en Java

El patrón de hilo único asegura que solo una enstancia del hilo se ejecute a la vez. Esto es útil para tareas que deben ejecutarse de manera continua en segundo plano, como la actualización periódica de tokens de acceso. A continuación, se muestra una implementación utilizando la interfaz Runnable.

public class HiloUnico implements Runnable {
    private static final String URL_TOKEN = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="
            + ConfiguracionParametros.APP_ID + "&secret=" + ConfiguracionParametros.APP_SECRET;
    
    private static volatile TokenAcceso tokenAcceso;

    private HiloUnico() {}

    private static class MantenedorHiloUnico {
        private static final HiloUnico INSTANCIA = new HiloUnico();
    }

    public static HiloUnico obtenerInstancia() {
        return MantenedorHiloUnico.INSTANCIA;
    }

    @Override
    public void run() {
        while (true) {
            try {
                HttpsURLConnection conexion = UtilHttp.iniciarConexionHttps(URL_TOKEN, "GET");
                String respuesta = UtilHttp.obtenerContenidoHttps(conexion, "utf-8");

                JSONObject json = respuesta != null ? JSON.parseObject(respuesta) : null;

                if (json != null) {
                    tokenAcceso = new TokenAcceso(json.getString("access_token"), json.getLong("expires_in"));
                } else {
                    System.out.println("Fallo al obtener el token de acceso----");
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

            try {
                long tiempoEspera = tokenAcceso != null ? (tokenAcceso.getTiempoExpiracion() - 200) * 1000 : 60 * 1000;
                Thread.sleep(tiempoEspera);
            } catch (InterruptedException e) {
                try {
                    Thread.sleep(60 * 1000);
                } catch (InterruptedException e1) {
                    e1.printStackTrace();
                }
            }
        }
    }

    public static TokenAcceso getTokenAcceso() {
        return tokenAcceso;
    }
}

Alternativamente, se puede extenedr la clase Thread:

public class HiloUnicoExtendido extends Thread {
    private static final String URL_TOKEN = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="
            + ConfiguracionParametros.APP_ID + "&secret=" + ConfiguracionParametros.APP_SECRET;
    
    private static volatile TokenAcceso tokenAcceso;

    private HiloUnicoExtendido() {}

    private static class MantenedorHiloUnicoExtendido {
        private static final HiloUnicoExtendido INSTANCIA = new HiloUnicoExtendido();
    }

    public static HiloUnicoExtendido obtenerInstancia() {
        return MantenedorHiloUnicoExtendido.INSTANCIA;
    }

    @Override
    public void run() {
        while (true) {
            try {
                HttpsURLConnection conexion = UtilHttp.iniciarConexionHttps(URL_TOKEN, "GET");
                String respuesta = UtilHttp.obtenerContenidoHttps(conexion, "utf-8");

                JSONObject json = respuesta != null ? JSON.parseObject(respuesta) : null;

                if (json != null) {
                    tokenAcceso = new TokenAcceso(json.getString("access_token"), json.getLong("expires_in"));
                } else {
                    System.out.println("Fallo al obtener el token de acceso----");
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

            try {
                long tiempoEspera = tokenAcceso != null ? (tokenAcceso.getTiempoExpiracion() - 200) * 1000 : 60 * 1000;
                Thread.sleep(tiempoEspera);
            } catch (InterruptedException e) {
                try {
                    Thread.sleep(60 * 1000);
                } catch (InterruptedException e1) {
                    e1.printStackTrace();
                }
            }
        }
    }

    public static TokenAcceso getTokenAcceso() {
        return tokenAcceso;
    }
}

En este caso, se utiliza un tokenn de acceso para comunicarse con los servidores de WeChat, que debe actualizarse cada dos horas. Se garantiza que solo un hilo se encarga de esta tarea para evitar conflictos.

La clase TokenAcceso es inmutable:

public class TokenAcceso {
    private final String token;
    private final long tiempoExpiracion;

    public TokenAcceso(String token, long tiempoExpiracion) {
        this.token = token;
        this.tiempoExpiracion = tiempoExpiracion;
    }

    public String getToken() {
        return token;
    }

    public long getTiempoExpiracion() {
        return tiempoExpiracion;
    }
}

Este patrón es útil cuando se requiere que un hilo se ejecute de manera continua y exclusiva, como en procesos de mantenimiento en segundo plano o actualizaciones regulares.

Etiquetas: java Singleton hilos patrones de diseño WeChat API

Publicado el 9-30 04:59