[Java] IllegalThreadStateException, wat doe ik verkeerd?

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

  • Twazerty
  • Registratie: April 2006
  • Laatst online: 23:53

Twazerty

AVCHDCoder developer

Topicstarter
Ik ben bezig om het een en ander multiThreaded te maken zodat er een hoop tijd bespaard kan worden. Maar om "duistere" reden krijg ik telkens een IllegalThreadStateException. Ik heb een ArrayList van alle Processen die uitgevoerd moeten worden. En ik heb een maximaal aantal lopende Threads ingesteld zodat niet alle processen uit de arraylist in 1x gaan lopen. Zodra er een Thread beschikbaar is mag de volgende uit de arraylist starten. Dit is de code waar het om gaat:

Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
      public void startConversie()
//hqSubtitles is een arraylist van alle Threads die uitgevoerd gaan moeten worden.
            int maxThreads = 2; //Max aantal Threads
            int lopendeThreads = 0; //Aantal lopende Threads

            //Wachten totdat alle ondertitels omgezet zijn.
            boolean completed = false;
            while(!completed){
                lopendeThreads = 0;
                completed = true;
                for(HQSubs s: hqSubtitles){
                    //Tel het aantal lopende Threads
                    if(s.isAlive()){
                        lopendeThreads++;
                    }
                    
                    if(!s.isCompleted()){
                        completed = false;
                    }
                }
                //Max aantal Threads niet bereikt dus code mag uitgevoerd worden.
                if(lopendeThreads < maxThreads){
                    for(HQSubs s: hqSubtitles){
                        Thread.sleep(100);
                        //Thread starten als deze nog niet completed is en het
                        //aantal lopende Threads kleiner is als het max aantal Threads
                        if(!s.isCompleted()){
                            s.start(); //Thread voor de eerste keer starten
                            lopendeThreads++; //Anders word alles gestart omdat lopendeThreads niet bijgewerkt word
                            Thread.sleep(1000); //Even wachten tot de Thread is gestart
                        }

                    }
                }
                Thread.sleep(100);//Even wachten om niet te veel belasting te creeren
            }
     }


En dit is de klasse HQSubs. Heb het daadwerkelijke process even weggehaald aangezien dat niet van belang is nu. Daar word onder andere gewoon een .bat file uitgevoerd en gaat naar completed = true; zodra dat process afgerond is. Niks bijzonders. Dat process loopt circa 20 minuten.

Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class HQSubs extends Thread{
    private boolean completed;

    public HQSubs(){
        completed = false;
    }
    
    @Override
    public void run(){
        //Doe vanalles.
        completed = true;
    }

    public boolean isCompleted() {
        return completed;
    }
}


De eerste 2 Threads worden uitgevoerd volgens plan. Gebeurt ook precies volgens mijn code. Zodra er 1 van de 2 Threads klaar is moet de volgende worden gestart omdat er nu maar 1 lopende Thread is. Op dat moment krijg ik de IllegalThreadStateException. Volgens mij betekend dat dat ik een Thread opnieuw aan wil maken wat niet mag. Alleen snap ik niet waarom ik deze Exception krijg. Wat doe ik verkeerd? Ik ben al uren bezig en kom er niet uit. Wie kan mij verder helpen?

Ruisende versterker: schakel je subwoofer in.


Acties:
  • 0 Henk 'm!

  • pedorus
  • Registratie: Januari 2008
  • Niet online
Het is mij niet helemaal duidelijk wat je nu wil doen (maar dat kan op dit moment ook aan mij liggen ;)), maar ik denk dat je een soort Thread Pool aan het implementeren bent, op een vreemde manier. Thread.Sleep() lijkt me in ieder geval zelden de beste optie, en het helpt ook als je aangeeft waar je precies Exceptions krijgt. ;)

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten


Acties:
  • 0 Henk 'm!

Verwijderd

Als 1 van je threads klaar is dan is 'lopendeThreads < maxThreads' en wordt er door hqSubtitles heen gelopen. Daar zit ook de thread nog in die bezig is, en ook die is '!s.isCompleted()'. Die probeer je vervolgens opnieuw te start()-en. Elke thread mag maar 1x gestart worden, en dat levert je fout op.

Overigens is dit ook niet de ideale manier om een threadpool te maken. Het is handiger om een aantal threads te starten, die zelf hun werk, in de vorm van Runnable's, ophalen bij een centraal object. De HQSubs klasse is dan geen subklasse meer van Thread, maar een implementatie van Runnable.

Overigens heeft java sinds versie 5 ingebouwde functies om thread-pools te maken. Kijk eens op http://java.sun.com/j2se/.../concurrent/Executor.html

Acties:
  • 0 Henk 'm!

  • Twazerty
  • Registratie: April 2006
  • Laatst online: 23:53

Twazerty

AVCHDCoder developer

Topicstarter
Inderdaad 8)7 dit is de oplossing:
Java:
1
2
3
4
5
                       if(!s.isCompleted() && !s.isAlive() && lopendeThreads < maxThreads){
                            s.start(); //Thread voor de eerste keer starten
                            lopendeThreads++; //Anders word alles gestart omdat lopendeThreads niet bijgewerkt word
                            Thread.sleep(1000); //Even wachten tot de Thread is gestart
                        }


Was natuurlijk wel handig om nogmaals op lopendeThreads < maxThreads te controleren en te controleren of de Thread niet leeft
Ik ga nog even zo'n Threadpool bekijken.

Ruisende versterker: schakel je subwoofer in.


Acties:
  • 0 Henk 'm!

  • Herko_ter_Horst
  • Registratie: November 2002
  • Niet online
Met Tubbie: Thread extenden is sowieso niet de juiste manier. Implementeer in plaats daarvan Runnable en start die Runnable op een Thread (uit een thread pool).

"Any sufficiently advanced technology is indistinguishable from magic."


Acties:
  • 0 Henk 'm!

  • bomberboy
  • Registratie: Mei 2007
  • Laatst online: 00:02

bomberboy

BOEM!

Die
Java:
1
Thread.sleep(1000);

blijft nog steeds fishy. Dat hoor je eigenlijk op te lossen met de beschikbare .wait() en .notify() methodes die daar voor gemaakt zijn. Dat is een goede (maar niet triviale) oefening om het threading en locking te leren begrijpen.
Voor praktische en real world implementaties zijn de reeds aangehaalde executors/callables/futures in de recente Java versies veel handiger en veel minder foutgevoelig. (Lees: dat zijn de wielen die je nu opnieuw probeert uit te vinden)

Acties:
  • 0 Henk 'm!

  • Twazerty
  • Registratie: April 2006
  • Laatst online: 23:53

Twazerty

AVCHDCoder developer

Topicstarter
bomberboy schreef op zondag 13 december 2009 @ 12:52:
Die
Java:
1
Thread.sleep(1000);

blijft nog steeds fishy. Dat hoor je eigenlijk op te lossen met de beschikbare .wait() en .notify() methodes die daar voor gemaakt zijn. Dat is een goede (maar niet triviale) oefening om het threading en locking te leren begrijpen.
Voor praktische en real world implementaties zijn de reeds aangehaalde executors/callables/futures in de recente Java versies veel handiger en veel minder foutgevoelig. (Lees: dat zijn de wielen die je nu opnieuw probeert uit te vinden)
Heb wel vaker het wiel opniew proberen uit te vinden. Dit vind ik wel een goede manier om meer insight te krijgen hoe het allemaal werkt. (Ben nog student ;) ) Heb nu het volgende voorbeeld gebruikt: http://www.ibm.com/developerworks/library/j-jtp0730.html
Dit werkt uitstekend. Max x aantal Threads en ze worden netjes allemaal uitgevoerd. Precies zoals ik het wil hebben. Maar daar komt ie:
Zodra ik alle "Threads" heb toegevoegd gaat mijn code gewoon verder. Hoe zorg ik ervoor dat de code niet doorloopt voordat alle Threads afgewerkt zijn? Toch maar middels een while die 1 voor 1 alle objecten controleert?

Ruisende versterker: schakel je subwoofer in.


Acties:
  • 0 Henk 'm!

  • pedorus
  • Registratie: Januari 2008
  • Niet online
Je gebruikt nu een artikel uit 2002... Waarom heb je niet gewoon de link uit de 1e reply gevolgt? Dan kom je vanzelf bij deze functie... :)

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten


Acties:
  • 0 Henk 'm!

  • bomberboy
  • Registratie: Mei 2007
  • Laatst online: 00:02

bomberboy

BOEM!

Twazerty schreef op zondag 13 december 2009 @ 13:23:
[...]
Heb wel vaker het wiel opniew proberen uit te vinden. Dit vind ik wel een goede manier om meer insight te krijgen hoe het allemaal werkt. (Ben nog student ;) )
Vandaar mijn opmerking : "Dat is een goede (maar niet triviale) oefening om het threading en locking te leren begrijpen."
Heb nu het volgende voorbeeld gebruikt: http://www.ibm.com/developerworks/library/j-jtp0730.html
Dit werkt uitstekend. Max x aantal Threads en ze worden netjes allemaal uitgevoerd. Precies zoals ik het wil hebben. Maar daar komt ie:
Zodra ik alle "Threads" heb toegevoegd gaat mijn code gewoon verder. Hoe zorg ik ervoor dat de code niet doorloopt voordat alle Threads afgewerkt zijn? Toch maar middels een while die 1 voor 1 alle objecten controleert?
http://java.sun.com/docs/...al/concurrency/index.html

Thread.join() is een oplossing, .wait() en .notify() is er ook één. In recente java versies heb je nog meer high level en elegantere oplossingen en dan zijn er ook de Callables en Futures die naar mijn gevoel het handigst zijn in 90% van de gevallen. (En op het eerste zicht ook hier.)

In ieder geval, als je bovenstaande tutorial doorneemt en alle oefeningentjes maakt en er zat mee experimenteert zou je normaal een degelijke basis moeten hebben om mee verder te gaan.
Pagina: 1