En aquest tema, explorarem el cicle de vida dels fils en Java. Els fils són una part fonamental de la programació concurrent i multithreading, i comprendre el seu cicle de vida és essencial per escriure aplicacions eficients i segures.

Conceptes Clau

  1. Cicle de Vida d'un Fil: Els fils passen per diversos estats des del moment en què es creen fins que finalitzen.
  2. Estats dels Fils: Els estats principals són: New, Runnable, Blocked, Waiting, Timed Waiting, i Terminated.
  3. Mètodes Clau: start(), run(), sleep(), wait(), notify(), notifyAll(), join().

Estats dels Fils

Els fils en Java poden estar en un dels següents estats:

Estat Descripció
New El fil ha estat creat però encara no ha començat.
Runnable El fil està preparat per executar-se i està esperant que el planificador de fils li assigni temps de CPU.
Blocked El fil està esperant per obtenir un monitor de bloqueig.
Waiting El fil està esperant indefinidament fins que un altre fil el notifiqui.
Timed Waiting El fil està esperant durant un període de temps específic.
Terminated El fil ha finalitzat la seva execució.

Diagrama del Cicle de Vida dels Fils

New -> Runnable -> Running -> (Blocked/Waiting/Timed Waiting) -> Runnable -> Terminated

Mètodes Clau

start()

El mètode start() inicia l'execució d'un fil. Quan es crida a aquest mètode, el fil passa de l'estat New a l'estat Runnable.

run()

El mètode run() conté el codi que s'executarà en el fil. Aquest mètode és invocat internament per start().

sleep(long millis)

El mètode sleep() fa que el fil actual es posi en estat Timed Waiting durant el temps especificat en mil·lisegons.

wait()

El mètode wait() fa que el fil actual es posi en estat Waiting fins que un altre fil cridi a notify() o notifyAll() en el mateix objecte.

notify() i notifyAll()

Els mètodes notify() i notifyAll() desperten un o tots els fils que estan esperant en el mateix objecte, respectivament.

join()

El mètode join() fa que el fil actual esperi fins que el fil en el qual es crida a join() finalitzi.

Exemple Pràctic

A continuació, es mostra un exemple pràctic que il·lustra el cicle de vida dels fils:

class SimpleThread extends Thread {
    public void run() {
        System.out.println(Thread.currentThread().getName() + " is running.");
        try {
            Thread.sleep(1000); // El fil es posa en estat Timed Waiting
        } catch (InterruptedException e) {
            System.out.println(e);
        }
        System.out.println(Thread.currentThread().getName() + " has finished.");
    }
}

public class ThreadLifecycleDemo {
    public static void main(String[] args) {
        SimpleThread t1 = new SimpleThread();
        SimpleThread t2 = new SimpleThread();

        System.out.println("State of t1 after creating it: " + t1.getState()); // New

        t1.start();
        t2.start();

        System.out.println("State of t1 after calling start(): " + t1.getState()); // Runnable

        try {
            t1.join(); // El fil principal espera que t1 finalitzi
            t2.join(); // El fil principal espera que t2 finalitzi
        } catch (InterruptedException e) {
            System.out.println(e);
        }

        System.out.println("State of t1 after it has finished: " + t1.getState()); // Terminated
    }
}

Exercicis Pràctics

Exercici 1: Crear i Executar Fils

  1. Crea una classe que implementi Runnable i sobreescriu el mètode run().
  2. Crea i inicia diversos fils utilitzant aquesta classe.
  3. Observa i imprimeix els estats dels fils en diferents punts del seu cicle de vida.

Exercici 2: Sincronització de Fils

  1. Crea una classe amb un mètode sincronitzat que incrementi un comptador.
  2. Crea diversos fils que cridin a aquest mètode.
  3. Utilitza wait() i notify() per coordinar els fils.

Solucions

Solució a l'Exercici 1

class MyRunnable implements Runnable {
    public void run() {
        System.out.println(Thread.currentThread().getName() + " is running.");
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            System.out.println(e);
        }
        System.out.println(Thread.currentThread().getName() + " has finished.");
    }
}

public class ThreadExercise1 {
    public static void main(String[] args) {
        Thread t1 = new Thread(new MyRunnable());
        Thread t2 = new Thread(new MyRunnable());

        System.out.println("State of t1 after creating it: " + t1.getState()); // New

        t1.start();
        t2.start();

        System.out.println("State of t1 after calling start(): " + t1.getState()); // Runnable

        try {
            t1.join();
            t2.join();
        } catch (InterruptedException e) {
            System.out.println(e);
        }

        System.out.println("State of t1 after it has finished: " + t1.getState()); // Terminated
    }
}

Solució a l'Exercici 2

class Counter {
    private int count = 0;

    public synchronized void increment() {
        count++;
        System.out.println(Thread.currentThread().getName() + " incremented count to: " + count);
    }
}

class CounterRunnable implements Runnable {
    private Counter counter;

    public CounterRunnable(Counter counter) {
        this.counter = counter;
    }

    public void run() {
        for (int i = 0; i < 5; i++) {
            counter.increment();
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                System.out.println(e);
            }
        }
    }
}

public class ThreadExercise2 {
    public static void main(String[] args) {
        Counter counter = new Counter();
        Thread t1 = new Thread(new CounterRunnable(counter));
        Thread t2 = new Thread(new CounterRunnable(counter));

        t1.start();
        t2.start();

        try {
            t1.join();
            t2.join();
        } catch (InterruptedException e) {
            System.out.println(e);
        }
    }
}

Conclusió

En aquest tema, hem explorat el cicle de vida dels fils en Java, incloent els diferents estats pels quals passen i els mètodes clau que controlen aquests estats. També hem vist exemples pràctics i exercicis per reforçar els conceptes apresos. Amb aquesta comprensió, estàs preparat per gestionar fils de manera efectiva en les teves aplicacions Java.

Curs de Programació en Java

Mòdul 1: Introducció a Java

Mòdul 2: Flux de Control

Mòdul 3: Programació Orientada a Objectes

Mòdul 4: Programació Orientada a Objectes Avançada

Mòdul 5: Estructures de Dades i Col·leccions

Mòdul 6: Gestió d'Excepcions

Mòdul 7: Entrada/Sortida de Fitxers

Mòdul 8: Multithreading i Concurrència

Mòdul 9: Xarxes

Mòdul 10: Temes Avançats

Mòdul 11: Frameworks i Llibreries de Java

Mòdul 12: Construcció d'Aplicacions del Món Real

© Copyright 2024. Tots els drets reservats