Avatar billede jespersahner Nybegynder
29. april 2006 - 21:09 Der er 9 kommentarer og
1 løsning

Afbryde gruppe af threads ved fejl

Jeg kører et program, der indeholder flere threads på flg. måde:

Thread t1, t2, t3;
...
t1.start();
t2.start();
t3.start();
t1.join();
t2.join();
t3.join();
...

Programmet vil altså vente på, at alle threads afsluttes. Hvis imidlertid blot en af disse threads opdager en fejl og returnerer til programmet, skal alle øvrige threads afbrydes og afsluttes.

Hvordan gør man det?
Avatar billede arne_v Ekspert
29. april 2006 - 21:49 #1
er det ikke bare en udbygning af modellen fra dit andet spørgsmål ?
Avatar billede arne_v Ekspert
29. april 2006 - 21:54 #2
package april;

import java.lang.Thread.UncaughtExceptionHandler;
import java.util.concurrent.Semaphore;

import javax.swing.JFrame;

public class RestartableAppMultiThreaded {
    private T1 t1;
    private T2 t2;
    private GUI f;
    private Semaphore sf = new Semaphore(1);
    public void initRestart() {
        t2.interrupt();
        try {
            t2.join();
        } catch (InterruptedException e) {
        }
        f.dispose();
        sf.release();
    }
    public void exec() {
        Thread.setDefaultUncaughtExceptionHandler(new Handler(this));
        while(true) {
            try {
                sf.acquire();
            } catch (InterruptedException e) {
            }
            t1 = new T1();
            t2 = new T2();
            f = new GUI();
            t1.start();
            t2.start();
            f.setVisible(true);
        }
    }
    public static void main(String[] args) {
        RestartableAppMultiThreaded er = new RestartableAppMultiThreaded();
        er.exec();
    }
}

class GUI extends JFrame {
    public GUI() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setTitle("Some GUI");
        setSize(300, 300);
    }
}

class T1 extends Thread {
    public void run() {
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
        }
        throw new RuntimeException("Oops");
    }
}

class T2 extends Thread {
    public void run() {
        boolean done = false;
        while(!done) {
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                done = true;
            }
        }
        System.out.println("T2 done");
    }
}

class Handler implements UncaughtExceptionHandler {
    private RestartableAppMultiThreaded app;
    public Handler(RestartableAppMultiThreaded app) {
        this.app = app;
    }
    public void uncaughtException(Thread t, Throwable e) {
        app.initRestart();
        System.out.println("Restarting ...");
    }
}
Avatar billede arne_v Ekspert
29. april 2006 - 21:55 #3
eller da vi ikke ved hvilken tråd der er gået ned:

package april;

import java.lang.Thread.UncaughtExceptionHandler;
import java.util.concurrent.Semaphore;

import javax.swing.JFrame;

public class RestartableAppMultiThreaded {
    private T1 t1;
    private T2 t2;
    private GUI f;
    private Semaphore sf = new Semaphore(1);
    public void initRestart() {
        t1.interrupt();
        t2.interrupt();
        try {
            t1.join();
            t2.join();
        } catch (InterruptedException e) {
        }
        f.dispose();
        sf.release();
    }
    public void exec() {
        Thread.setDefaultUncaughtExceptionHandler(new Handler(this));
        while(true) {
            try {
                sf.acquire();
            } catch (InterruptedException e) {
            }
            t1 = new T1();
            t2 = new T2();
            f = new GUI();
            t1.start();
            t2.start();
            f.setVisible(true);
        }
    }
    public static void main(String[] args) {
        RestartableAppMultiThreaded er = new RestartableAppMultiThreaded();
        er.exec();
    }
}

class GUI extends JFrame {
    public GUI() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setTitle("Some GUI");
        setSize(300, 300);
    }
}

class T1 extends Thread {
    public void run() {
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
        }
        throw new RuntimeException("Oops");
    }
}

class T2 extends Thread {
    public void run() {
        boolean done = false;
        while(!done) {
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                done = true;
            }
        }
        System.out.println("T2 done");
    }
}

class Handler implements UncaughtExceptionHandler {
    private RestartableAppMultiThreaded app;
    public Handler(RestartableAppMultiThreaded app) {
        this.app = app;
    }
    public void uncaughtException(Thread t, Throwable e) {
        app.initRestart();
        System.out.println("Restarting ...");
    }
}
Avatar billede jespersahner Nybegynder
30. april 2006 - 11:26 #4
->arne_v: Jo, det er nok en udbygning af tidligere spm.

Min grundlæggende udfordring er at genstarte min applikation, når der indtræffer fejl, som ikke håndteres. Sådanne fejl optræder i mit tilfælde fra eksterne klasser, som jeg bruger og derfor ikke har indflydelse på. At fange fejl løses af imidlertid af Thread.setDefaultUncaughtExceptionHandler, som virker "globalt" i forhold til alle fejl, der måtte indtræffe.

Det næste problem er så at få ryddet op. Jeg forsøger da som i dit eksempel at interrupt'e alle tråde, jeg har startet op, herunder dispose'e alle JFrames, og i øvrigt sætte alle tråd-referencer til 'null' inden genstart (nok lidt ligegyldigt, da referencerne jo etableres på ny ved genstart).

Imidlertid "fryser" applikationen efter genstart, og jeg gætter på, at det skyldes, at jeg ikke får ryddet alt op - altså noget med at visse bagved kørende tråde (sat i gang af mine eksterne klasser) ikke bliver afsluttet og derfor holder på ressourcer, som den genstartede applikation skal bruge.

Selv i dit eksempel med interrupt, dispose og release kan man vel ikke være sikker på, at alle bagved kørende tråde afsluttes (altså hvis T1 eller T2 starter andre tråde osv.) eller..?

Hvis jeg forstår dette ret, savner jeg en slags funktionalitet (måske findes den uden mit kendskab), hvor man ved interrupt af en tråd også interrupte'r alle tråde, som denne måtte have sat i gang, så man altså er 100% sikker på at få ryddet alt op, herunder eventuelle deadlocks.

Men måske er dette nonsens (?) En tråd kan vel meget vel starte en anden tråd op uden at holde en reference til denne tråd (altså bare med new Thread()), og hvis denne anden tråd ender i en deadlock, har man balladen.

En måde at løse genstarts-problemet på, hvor man i stedet for den beskrevne "varme" genstart laver en "kold" genstart, kunne være at starte applikationen i en anden JVM. Herved kan man ved fejl skyde applikationen ned med System.exit(0) og derefter starte forfra. Det er dog ikke videre elegant og burde nok ikke være nødvendigt.
Avatar billede arne_v Ekspert
30. april 2006 - 17:31 #5
måske noget a la:

        ThreadGroup tg = Thread.currentThread().getThreadGroup();
        int nt = tg.activeCount();
        Thread[] t = new Thread[nt];
        tg.enumerate(t);
        for(int i = 0; i < nt; i++) {
            if(t[i] != Thread.currentThread()) {
                t[i].interrupt();
            }
        }
Avatar billede webster Nybegynder
01. maj 2006 - 11:50 #6
Hej, som jeg var lidt inde på i din anden tråd så findes der ikke nogen 100% sikker måde at lukke tråde ned og få frigivet resourcer som denne/disse tråde holder. Hvis tråden først er deadlocked på en monitor så kan du hellere ikke interupte den (afaik). Det her problem er en af bevæggrundende for sun's barcelona/joe projekt der søger at implementere en mvm (multi-virtual machine eller noget i den dur) hvor dele af applicationen kan anbringes i en isolate og kontrolleres som var det et selvstændigt program. Det er desværre bare ikke færdigt endnu (de har teknisk set en beta ude at deres mvm men ved ikke noget om hvor klar den er til et produktions miljø).
Avatar billede jespersahner Nybegynder
01. maj 2006 - 18:53 #7
Måske kan man bruge "Echidna" (jeg kan dog ikke lige finde web-siden, underligt?), men ellers beskrevet i f.eks. http://www.onjava.com/pub/a/onjava/2001/09/25/optimization.html

Har I nogen erfaring med denne type værktøjer?
Avatar billede jespersahner Nybegynder
01. maj 2006 - 18:58 #8
Her er noget http://sourceforge.net/projects/echidna/, men den officielle hjemmeside findes vist ikke. Jeg ved ikke, om det stadig supporteres, eller der er kommet noget andet siden (?)
Avatar billede jespersahner Nybegynder
13. maj 2006 - 04:14 #9
->arne_v: Smid gerne et svar.
Avatar billede arne_v Ekspert
13. maj 2006 - 04:16 #10
svar
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester