Toon posts:

[java] Thread geblokeerd ?

Pagina: 1
Acties:

Verwijderd

Topicstarter
Beste Medetweaker,

Ik zit met een gaar probleem waar ik al een tijd op zit
te tubben en ik kom er niet uit. Wellicht dat een van jullie
mij het licht kan laten zien.

Het gaat over het volgende:
-Ik heb een listener class voor een scan apparaat.
Hierin wordt een functie aangeroepen en een status doorgegeven
als deze van status veranderd. (1 = idle, 2 = offline, 3 = actie
4 = pause / error, 5 klaar)

Wat doe ik nou, ik maak een listener aan op die class en als de status
1 (idle) is dan start ik de scanner. Nu kan ik precies nagaan
wat de status is. Op het moment dat de status 5 is dan kan ik aangeven
dat de listener gestopt moet worden.

Om dat allemaal in goede banen te leiden heb ik 2 functies in die class
aangemaakt te weten setDone en waitDone.
code:
1
2
3
4
5
6
7
8
private void setDone() {
      synchronized (condition) {
          done = true;
          //Log.logEvent("BaseCallback","waitDone","notify, done set to true");
          condition.notifyAll();
          //Log.logEvent("BaseCallback","waitDone","notify done");
      }
  }

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public void waitDone() {
      //Log.logEvent("BaseCallback","waitDone","Enter waitDone");
      synchronized (condition) {
         //Log.logEvent("BaseCallback","waitDone","condition synched");
          if (!done) 
          {
              //Log.logEvent("BaseCallback","waitDone","!done");
              try {
                  //Log.logEvent("BaseCallback","waitDone","before wait");
                  condition.wait();
                  //Log.logEvent("BaseCallback","waitDone","after wait");
              } catch (InterruptedException e) {
                 //Log.logEvent("BaseCallback","waitDone","InterruptedException " +e.getMessage());
              }
          }
      }
  }


En in diezelfde class heb ik de volgende variabelen gedefinieerd:
private Object condition;
private static boolean done = false;

Het probleem is nu het volgende:
Op het moment dat ik in de status 5 kom roep ik setDone(); aan.
Echter zover kom ik niet eens.
Wat wil het nu, als ik de class "Scanner" aanmaak dan roep ik daarna
ook scanner.waitDone(); aan. Echter deze gaat rechtstreeks naar
de codeline : condition.wait() toe en gaat daar lekker wachten en vervolgens
doet mijn class "Scanner" ook niks meer.

Wat je zou verwachten is dat als ik scanner aanmaak dat deze een "lock" op condition
zet. En als ik dan waitDone() aanroep dan zou deze toch bij synchronisatie
in de wacht gezet moeten worden. Dan kan "scanner" gewoon zijn werk doen, op het moment
dat status 5 de functie setDone aanroept dan wordt er gesynchroniseerd.
Hierdoor kan er verder gegaan worden via de notify functie (notifyAll is niet nodig
omdat er niet meerdere threads staan te wachten)

Heeft iemand een idee waar mijn denk/progammeer/pruts fout zit ?

Bedankt :)

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

2 dingen
1) je moet zorgen dat je je conditie bij die wait done in een while lus gaat checken.

code:
1
2
while(!done)
      condition.wait();

In dit geval zal het wel goed gaan, maar gewoonlijk weet je niet welke waarde je conditie heeft gekregen. Je weet alleen dat er iets veranderd is.. dus je zult moeten rechecken

2) zorg dat je de interrruptedexception niet gaat afvangen. Als een thread een signaal krijgt dat hij moet stoppen met wachten (interrupt) dan moet jij op de goeie manier hiermee omgaan. Resources vrijgeven (bv allerlei locks). Eventueel kun je Thread.currentThread.Interrupt aanroepen om aan te geven dat de thread op zijn sodemieter heeft gehad, en het signaal boven verder te laten afvangen. Het de isInterrupted vlag kan je zelf trouwens ook zo nu en dan in de gaten houden om te controleren of jouw thread de opdracht heeft gekregen om te gaan stoppen. Dit is beter dan een THread.stop doordat je netjes je respources kunt opruimen.


Gooi die output eens aan en post dat hier eens.

[ Voor 20% gewijzigd door Alarmnummer op 13-01-2005 18:33 ]


Verwijderd

Topicstarter
Ok, ik heb een deel relevante log erop gezet, met commentaarcode
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
device->init:entered
device->init:finished
device->addScanFileLoc:entered
device->reloadButtons:entered
device->onShow:GUIDlabels mtiff
device ->onShow:Currently not scanning
device ->onShow:Creating ScanControl
device ->onShow:start scanning
device->onShow:listener added
device->onShow:Waiting for scan is done
//hier wordt waitDone(); aangeroepen
//BaseCallback is de scanner class
BaseCallback->waitDone:Enter waitDone
BaseCallback->waitDone:condition synched
BaseCallback->waitDone:before wait
//hier worden wel nog scan events afgevuurd
BaseCallback->scanEventOccurred:state 1
BaseCallback->scanEventOccurred:state 3
//en nu hangen we

Ik heb waitDone veranderd in
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public void waitDone() {
      Log.logEvent("BaseCallback","waitDone","Enter waitDone");
      synchronized (condition) {
         Log.logEvent("BaseCallback","waitDone","condition synched");
          while(!done) 
          {
             // Log.logEvent("BaseCallback","waitDone","!done");
              try {
                  Log.logEvent("BaseCallback","waitDone","before wait");
                  condition.wait();
                 // Log.logEvent("BaseCallback","waitDone","after wait");
              } catch (InterruptedException e) {
              Log.logEvent("BaseCallback","waitDone","InterruptedException " +e.getMessage());
               break;
              }
          }
      }
  }

Ik heb het try catch blok er nog wel omheen laten zitten (er af halen maakte niks uit voor de werking) Belandde de thread maar in de exception, das tenminste nog iets. :(

Zijn er nog andere manieren bekend om te kijken of er threads geeindigd zijn, bovenstaande manier vind ik zelf het netst. Maar om te gaan luisteren naar een globale boolean is het ook weer niet.
*zucht*

Wat ik wel weet is dat als ik dus niet ga luisteren naar de waitDone dat de scanner wel z'n werk doet maar dan weet ik niet wanneer deze klaar is waar ik wel op moet wachten.

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

Hoe start je de threads op? (niet te veel code aub). (Lees... post alleen de basics)

[ Voor 25% gewijzigd door Alarmnummer op 14-01-2005 10:43 ]


Verwijderd

offtopic:
als je de code met een [ code=java ] tag opent i.p.v. een gewone [ code ] tag krijg je kleurtjes :)
Leest wat makkelijker

[ Voor 10% gewijzigd door Verwijderd op 14-01-2005 10:28 ]


Verwijderd

Topicstarter
Verwijderd schreef op vrijdag 14 januari 2005 @ 10:27:
offtopic:
als je de code met een [ code=java ] tag opent i.p.v. een gewone [ code ] tag krijg je kleurtjes :)
Leest wat makkelijker
Dan doe ik helemaal speciaal voor jou de kleurtjes :P

De threads start ik gewoon zo op
Java:
1
2
3
4
5
6
7
8
9
10
11
/*door sc in deze thread aan te maken heb ik van hier
ook nog controle om bijvoorbeeld de 
scanner te stoppen als er exceptions op treden of te cancellen
indien de gebruiker dit wil.
*/
ScanControl sc = new ScanControl();
BaseCallback bcb = new BaseCallback(sc);
bcb.start();
//nog wat code 
//wachten tot de scanner klaar is
bcb.waitDone();

  • Bobco
  • Registratie: Januari 2001
  • Laatst online: 30-10-2023

Bobco

I used to dream about Verona.

Die ScanControl en BassCallbck classes, implementeren die Runnable of extenden ze Thread? Ik implementeer meestal Runnable en start de threads dan met
Java:
1
2
MijnEigenThreadGeval dinges = new MijnEigenThreadGeval();
new Thread(dinges).start();

With the light in our eyes, it's hard to see.


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

Ik heb verder te weinig informatie om hier echt iets zinnigs mee te kunnen. Ik zou even een mini voorbeeld maken...dus wachten op afronden van een thread.

Verwijderd

Topicstarter
Ok, ik heb het nu anders opgepakt. Om de informatie op dit forum volledig te maken. Ik heb er zelf ook een hekel aan als mensen de uiteindelijke oplossing hebben en ze er niet posten (al is het uit gemakzucht)
Wat ik gedaan heb is die hele synchronisatie -poepamagatie uit de code gesloopt.
Vervolgens heb ik in de functie waar de statussen getriggered worden (code 5 in mijn geval)
de code neergezet om een nieuwe thread op te starten die het te scannen bestand moet oppakken. (Dat werkt nu wel en de rest blijft niet op elkaar wachten.)
Dus gewoon verder gaan op het punt waar je verwacht dat de code uit moet komen eigenlijk. Brengt natuurlijk enig risico met zich mee, maar is aanvaardbaar :)
Grappige is dat als de status 5 is bereikt dan heb ik nog niet het benodigde bestand van de scanner, dus heb ik daar wel een listener voor kunnen bouwen die wacht tot het bestand geschreven is.
In ieder geval bedankt voor jullie hulp!

Verwijderd

jammer dat ik deze post niet eerder heb gezien. want
tis nu een beetje mosterd na de maaltijd, maar ik wou het toch even kwijt.
de setDone() en waitDone() combo uit de startpost werkt niet omdat
je synced op condition in waitDone(), en daarna wacht je in setDone() totdat diezelfde lock vrij komt voordat je met condition.notifyAll() de lock unlockt
voila, een deadlock.

dus alleen dit in setDone() en dan werkt 't zoals je wilt
Java:
1
2
3
4
5
private void setDone() {
    done = true;
    //Log.logEvent("BaseCallback","waitDone","notify, done set to true");
    condition.notifyAll();
}

en de if (!done) moet een while zijn in waitDone() zoals al gezegd omdat je ook uit de condition.wait() kan komen door een andere interrupt dan waar je op zat te wachten.

[ Voor 32% gewijzigd door Verwijderd op 29-01-2005 05:05 ]


Verwijderd

Topicstarter
ReSc,
Bedankt voor de tip. Zodra ik beter (heb griep) ben ga ik dat eens testen :)
En laat ik het hier weten.
Pagina: 1