Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Join, interrupt i volatile

Join

Un join fa que un fil s’esperi a la finalització d’un altre. El fil que fa el join passa a l’estat WAITING fins que el fil que s’espera acaba. Si el fil que s’espera ja ha acabat, el join no fa res.

public class JoinThread {
    static class MyRunnable implements Runnable {
        @Override
        public void run() {
            log("starting");
            spend(1500);
            log("ending");
        }
    }

    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(new MyRunnable(), "child");
        log("starting");
        thread.start();
        log("started");
        thread.join();
        log("joined");
    }
}

Interrupt

Una interrupció és una indicació a un fil de què ha de parar de fer el que està fent i fer una altra cosa. Els fils tenen un flag que indica si han estat interromputs o no. Hi ha dues formes de comprovar si un fil ha estat interromput:

  • Que el fil faci crides freqüents a mètodes que facin throw de InterruptedException. Per exemple, Thread.sleep(). També serveix si la interrupció s’ha produït abans del sleep().
  • Que el fil comprovi freqüentment Thread.currentThread().isInterrupted().

Un cop feta la comprovació i detectada la interrupció, el flag d’interrupció del fil es retorna a false i cal decidir què fer. Normalment, el que farà és acabar la seva execució, però no és obligatori. Si no es fa res, el fil continuarà executant-se.

public class Interrupt1Thread {
    static class MyRunnable implements Runnable {
        @Override
        public void run() {
            log("starting");
            try {
                Thread.sleep(1500);
            } catch (InterruptedException e) {
                log("interrupted!");
            }
            log("ending");
        }
    }

    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(new MyRunnable(), "child");
        log("starting");
        thread.start();
        log("started");
        thread.interrupt();
        thread.join();
        log("joined");
    }
}
public class Interrupt2Thread {
    static class MyRunnable implements Runnable {
        @Override
        public void run() {
            log("starting");
            while (!Thread.currentThread().isInterrupted())
                ;
            log("ending");
        }
    }

    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(new MyRunnable(), "child");
        log("starting");
        thread.start();
        log("started");
        rest(1500);
        thread.interrupt();
        thread.join();
        log("joined");
    }
}

Estat compartit

Es pot acabar un fil compartint una variable que un fil modifica i l’altre llegeix. En Java, cal definir la variable com a volatile, indicant que els canvis fets en un fil siguin visibles en la resta. O bé utilitzar objectes segurs creats per nosaltres (mecanismes de sincronització) o d’una llibreria segura (p. ex. la atomic de Java).

La paraula clau volatile només s’ha d’utilitzar si un fil escriu i l’altre (o altres) llegeixen. Si diversos fils escriuen i llegeixen, cal gestionar-ho com a zones crítiques.

public class VolatileThread {

    static class SharedObject {
        boolean done; // volatile keyword needed
    }

    static class MyRunnable1 implements Runnable {
        SharedObject so;

        MyRunnable1(SharedObject so) {
            this.so = so;
        }

        @Override
        public void run() {
            spend(1500);
            so.done = true;
        }
    }

    static class MyRunnable2 implements Runnable {
        SharedObject so;

        MyRunnable2(SharedObject so) {
            this.so = so;
        }

        @Override
        public void run() {
            boolean done = false;
            while (!done) {
                done = so.done;
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        SharedObject so = new SharedObject();
        Thread t1 = new Thread(new MyRunnable1(so));
        Thread t2 = new Thread(new MyRunnable2(so));
        t1.start();
        t2.start();
        t1.join();
        log("joined 1 with " + so.done);
        t2.join();
        log("joined 2 with " + so.done);
    }
}
Last change: , commit: 0b1c1c5