Simulación Java Multihilo del Bucle Temporal en la Película 'Triangle'

Este programa emplea Java multihilo para replicar el ciclo central de la película 'Triangle', utilizendo conceptos como hilos que escapan, contaminación de recursos compartidos y recursión infinita.

import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Simulación del bucle temporal de 'Triangle' mediante hilos en Java.
 * Metáforas:
 * - El barco = espacio de memoria compartida.
 * - Hilos Jessie = procesos demoníacos incontrolables.
 * - Cuerpos/colgantes = fugas de memoria no recolectadas.
 * - Lista de recuerdos = lecturas de datos sucios que causan déjà vu.
 * - Bucle infinito = recursión sin condición de terminación.
 */
public class SimuladorBucleInfinito {

    // Recursos compartidos (el barco)
    static class Embarcacion {
        // Contador de cuerpos (solo aumenta, nunca disminuye)
        final AtomicInteger contadorCadaveres = new AtomicInteger(0);
        // Contador de colgantes (incrementa con cada llegada)
        final AtomicInteger contadorCollares = new AtomicInteger(0);
        // Memoria compartida – datos residuales no seguros para hilos
        final List<string> memorias = new CopyOnWriteArrayList<>();
        // Hilos Jessie activos (para detección mutua)
        final Set<Thread> jessiesActivos = ConcurrentHashMap.newKeySet();

        // Imprime estado actual de recursos
        void mostrarEstadisticas(String accion) {
            System.out.printf("[Recursos] %s | Cuerpos: %d | Collares: %d | Memorias: %d | Jessie activos: %d%n",
                    accion, contadorCadaveres.get(), contadorCollares.get(),
                    memorias.size(), jessiesActivos.size());
        }
    }

    // Hilo Jessie (proceso incontrolable)
    static class Jessie implements Runnable {
        private final int identificador;
        private final Embarcacion barco;
        private final Random aleatorio = new Random();
        private boolean tieneRecuerdo = false;

        // Límite global para evitar ejecución indefinida (demostración)
        private static final int MAX_JESSIE = 8;
        private static final AtomicInteger jessiesCreados = new AtomicInteger(0);

        Jessie(int id, Embarcacion barco) {
            this.identificador = id;
            this.barco = barco;
            jessiesCreados.incrementAndGet();
        }

        @Override
        public void ejecutar() {
            Thread hiloActual = Thread.currentThread();
            String nombre = "Jessie-" + identificador;
            hiloActual.setName(nombre);

            // 1. Abordar el barco – inicio de fuga de hilo
            barco.jessiesActivos.add(hiloActual);
            barco.contadorCollares.incrementAndGet(); // Cada llegada añade un collante (fuga)
            System.out.println(nombre + " abordó, collantes+1");

            // 2. Detección de contaminación de memoria (déjà vu)
            if (!barco.memorias.isEmpty()) {
                tieneRecuerdo = true;
                System.out.println(nombre + " siente familiaridad, hay " + barco.memorias.size() + " registros en memoria");
            }
            // Agregar recuerdo actual (dato sucio)
            barco.memorias.add(nombre + " recuerdo: timestamp=" + System.currentTimeMillis());
            System.out.println(nombre + " dejó un recuerdo");

            // 3. Simular movimiento en el barco, posible encuentro con otros Jessie
            try {
                int tiempoEstadia = 5000 + aleatorio.nextInt(5000);
                long inicio = System.currentTimeMillis();
                while (System.currentTimeMillis() - inicio < tiempoEstadia) {
                    Thread.sleep(1000);

                    // Descubrir otros Jessie – consecuencia de múltiples hilos escapados
                    for (Thread otro : barco.jessiesActivos) {
                        if (otro != hiloActual && otro.isAlive()) {
                            System.out.println(nombre + " encontró a " + otro.getName() + ", conflicto inminente");

                            // Decisión aleatoria: eliminar al otro o ser eliminado
                            if (aleatorio.nextBoolean()) {
                                System.out.println(nombre + " eliminó a " + otro.getName());
                                barco.contadorCadaveres.incrementAndGet(); // Cuerpo añadido, fuga de memoria
                                barco.jessiesActivos.remove(otro);
                                otro.interrupt(); // Terminación forzada del hilo
                                System.out.println(nombre + " cuerpos+1, actual: " + barco.contadorCadaveres.get());
                            } else {
                                System.out.println(nombre + " fue eliminado por " + otro.getName());
                                barco.contadorCadaveres.incrementAndGet(); // Cuerpo propio añadido
                                barco.jessiesActivos.remove(hiloActual);
                                System.out.println(nombre + " muerte, cuerpos+1, actual: " + barco.contadorCadaveres.get());
                                return; // Hilo finaliza
                            }
                        }
                    }

                    // Evento aleatorio: encuentro con pasajeros
                    if (aleatorio.nextInt(100) < 30) {
                        System.out.println(nombre + " vio a otros pasajeros, sin incidentes");
                    }
                }
            } catch (InterruptedException e) {
                System.out.println(nombre + " hilo interrumpido, muerte");
                barco.jessiesActivos.remove(hiloActual);
                return;
            }

            // 4. Supervivencia – pero defecto de código inicia nuevo ciclo (recursión)
            barco.jessiesActivos.remove(hiloActual);
            System.out.println(nombre + " completó el ciclo, regresa al muelle");

            // Defecto: sin condición de parada, se crea un nuevo Jessie (salvo límite demo)
            int creados = jessiesCreados.get();
            if (creados < MAX_JESSIE) {
                System.out.println(nombre + " no puede liberar su obsesión, vuelve a abordar -> creando Jessie-" + (creados + 1));
                Jessie siguienteJessie = new Jessie(creados + 1, barco);
                Thread siguienteHilo = new Thread(siguienteJessie::ejecutar);
                siguienteHilo.start();
            } else {
                System.out.println("===== Límite de demostración alcanzado, no se crean más hilos =====");
                barco.mostrarEstadisticas("Estado final");
            }
        }
    }

    // Programa principal (perspectiva de la muerte)
    public static void main(String[] args) throws InterruptedException {
        System.out.println("=== Inicio simulación: Bucle temporal en 'Triangle' ===");
        Embarcacion barco = new Embarcacion();

        // Primer Jessie – hilo original
        Jessie primerJessie = new Jessie(1, barco);
        Thread hilo1 = new Thread(primerJessie::ejecutar);
        hilo1.start();

        // Simular inyección periódica de nuevos Jessie (la muerte no puede controlar los hilos)
        ScheduledExecutorService inyector = Executors.newScheduledThreadPool(1);
        inyector.scheduleAtFixedRate(() -> {
            int proximoId = Jessie.jessiesCreados.get() + 1;
            if (proximoId <= Jessie.MAX_JESSIE) {
                System.out.println("\n[Inyección] La muerte no logró detenerlo, nuevo Jessie-" + proximoId + " escapa al barco");
                Jessie extraJessie = new Jessie(proximoId, barco);
                Thread hiloExtra = new Thread(extraJessie::ejecutar);
                hiloExtra.start();
            } else {
                inyector.shutdown();
            }
        }, 3, 2, TimeUnit.SECONDS);

        // Forzar fin tras 30 segundos
        Thread.sleep(30000);
        System.out.println("\n=== Tiempo agotado, intentando recolectar hilos (llega la muerte) ===");
        inyector.shutdownNow();
        for (Thread t : barco.jessiesActivos) {
            t.interrupt();
        }
        barco.mostrarEstadisticas("Terminación forzada");
        System.out.println("=== Simulación finalizada ===");
        System.exit(0);
    }
}
</string>

Correspondencia entre escena de película y código

Escena de 'Triangle' Mapeo en el programa
Jess engaña a la muerte y no baja del barco El hilo no termina normalmente, escapa a memoria compartida (el barco)
Cada vez que sube al barco, lleva un collante contadorCollares.incrementAndGet() – objetos que solo aumentan, fuga de memoria
Cuerpos quedan en el barco tras asesinatos contadorCadaveres.incrementAndGet() – igual fuga, el recolector de basura no los libera
Ciclos dejan recuerdos residuales Lista memorias crece continuamente, causando déjà vu por lectura de datos sucios
Múltiples Jessies coexisten simultáneamenet Conjunto jessiesActivos con varios hilos ejecutándose en paralelo
Jessies se cazan entre sí Hilos iteran jessiesActivos, eliminan aleatoriamente a otros o son eliminados
Pensar que ha vuelto a casa, pero comienza nuevo ciclo Método ejecutar() crea recursivamente un nuevo hilo Jessie al final
Programa sin condición de terminación real Solo limitado por MAX_JESSIE para demostración; sin él, sería bucle infinito
La muerte no puede detener procesos escapados Hilo principal intenta interrumpir, pero algunos hilos pueden quedar bloqueados

Ejemplo de salida (fragmento)

=== Inicio simulación: Bucle temporal en 'Triangle' ===
Jessie-1 abordó, collantes+1
Jessie-1 dejó un recuerdo
[Recursos] Jessie-1 abordó | Cuerpos: 0 | Collares: 1 | Memorias: 1 | Jessie activos: 1
...
[Inyección] La muerte no logró detenerlo, nuevo Jessie-2 escapa al barco
Jessie-2 abordó, collantes+1
Jessie-2 siente familiaridad, hay 2 registros en memoria
Jessie-2 dejó un recuerdo
Jessie-1 encontró a Jessie-2, conflicto inminente
Jessie-1 eliminó a Jessie-2
Jessie-1 cuerpos+1, actual: 1
...
Jessie-3 abordó, collantes+1
...
===== Límite de demostración alcanzado, no se crean más hilos =====
[Recursos] Estado final | Cuerpos: 7 | Collares: 8 | Memorias: 12 | Jessie activos: 2

Para simular más fielmente la fuga de hilos, se puede aumentar MAX_JESSIE y ejecutar por tiempo prolongado, observando el crecimiento de cuerpos, collantes y memorias hasta un posible desbordamiento de memoria. Eliminando MAX_JESSIE, el programa entrará en recursión infinita, imitando un sistema colapsado. Agregar Thread.sleep(0) puede intensificar la competencia entre hilos, haciendo los conflictos más impredecibles.

Etiquetas: java multihilo concurrencia AtomicInteger CopyOnWriteArrayList

Publicado el 7-23 18:59