[Java] Thread stoppen

Pagina: 1
Acties:
  • 129 views sinds 30-01-2008
  • Reageer

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
Ik heb een vraagje over een ontwerp kwestie over stoppen thread. het Thread.stop() commando is depricated:

This method is inherently unsafe. Stopping a thread with
Thread.stop causes it to unlock all of the monitors that it
has locked (as a natural consequence of the unchecked
ThreadDeath exception propagating up the stack). If
any of the objects previously protected by these monitors were in
an inconsistent state, the damaged objects become visible to
other threads, potentially resulting in arbitrary behavior. Many
uses of stop should be replaced by code that simply
modifies some variable to indicate that the target thread should
stop running. The target thread should check this variable
regularly, and return from its run method in an orderly fashion
if the variable indicates that it is to stop running. If the
target thread waits for long periods (on a condition variable,
for example), the interrupt method should be used to
interrupt the wait.

Oke, dit snap ik :) Maar stel dat niet de mogelijkheid heb om in de run methode te gaan kijken naar die variable? Bijvoorbeeld: ik roep een tijdsconsumerende routine aan in een api (in mijn geval in een gegenereerde routine) en daar kan ik niet kijken naar die variable (omdat de source elke keer gegenereerd wordt of omdat je geen toegang tot de source hebt). Hoe zou ik dit probleem moeten fixen?

  • Jelmer
  • Registratie: Maart 2000
  • Laatst online: 07:36
Je moet toch op zn minst 1 var. laten cheken als je een lus in je run hebt.. en ff een boolean checken kost waarschijnlijk niet eens zoveel tijd..

  • wasigh
  • Registratie: Januari 2001
  • Niet online

wasigh

wasigh.blogspot.com

maak een zelfde implementatie als de Thread.stop() methode. (Gooit een DeadThread exception oid..) niet mooi maar volgens mij het enige wat mogelijk is...

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
De methode implementeren wordt vrij lastig omdat het de stop methode in feite niets anders doet dan security afhandelen en een een native methode aanroepen. Die native methode implementeren zal niet makkelijk werken.

Helaas denk ik toch dat je het beste een oplossing kunt zoeken voor je probleem. Een thread op deze brute wijze stoppen zorgt voor nogal wat ongedefinieerd gedrag. Het beste kan je toch gewoon een soort stop-request methode maken en dit checken in de thread.

De enige wijze waarop dit echt niet werkt is blocking-io en dat is in dit geval als ik het goed begrijp niet zo. Bovendien zou je als dat wel het geval is nio kunnen gebruiken.

Over het algemeen is het toch ook geen probleem als je Thread nog even doorgaat voordat hij op je stop-request in gaat?

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
Op vrijdag 23 november 2001 23:24 schreef Jelmer Barhorst het volgende:
Je moet toch op zn minst 1 var. laten cheken als je een lus in je run hebt.. en ff een boolean checken kost waarschijnlijk niet eens zoveel tijd..
Zoals boven vermeld word, ik kan niet kijken naar een flag omdat de source code gegenereerd wordt en elke wijziging erin verdwijnt als ik nieuwe code genereer (een parser).En deze oplossing zou ook niet werken als je een lib gebruikt waarvan je de source niet hebt, en geen mogelijkheid om te veranderen (dus checks toe te voegen).

Maar ik zie dus dat er geen andere oplossing is.

  • The - DDD
  • Registratie: Januari 2000
  • Laatst online: 03-09 16:40
Ok, ik ruik... Strategy Pattern.

Wat je dan doet is dat je een Thread object hebt wat altijd hetzelfde is, de implementatie hangt er als een apart object onder. Dit Strategy object genereer je en geef je aan je Thread object. Deze gaat dat Object vervolgens in zijn Run methode aanroepen.

Enige wat belangrijk is, is dat het gegenereerde object een bepaalde standaard public methode bevat.

Wat je dus eigenlijk doet is de wisselende implementatie UIT je thread halen en in een aprat object stoppen. Dit object ga je vervolgens in je thread runnen. Per loop van de run roep je de methode 1 keer aan. Tegelijker tijd kun je dan ten alle tijden de thread runnen. Verder is het nu makkelijk om ook een standaard opruim methode te definieren in je Strategy object. Zodat je zeker weet dat eventuele externe locks weg gehaald worden. (bv. een lock op een database)


Simpel gezegd, je hebt in weze een thread klaar staan die op zichzelf al kan draaien.

Even wat code om je op weg te helpen.
code:
1
2
3
4
public interface StrategyObj {
   public abstract void execute(); // eventuele throws moet je hier ook definiëren
   public abstract void cleanup();
}


code:
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
..
   private boolean keepgoing = true;

   StrategyObj TheWork = null;

   public synchronized startThread(StrategyObj _TheWork)
   {
      if (TheWork == null)
      {
        TheWork = _TheWork;
        this.Start();
      }
      else
      { /* throw hier een exception zodat de aanroeper weet dat het object al bezig is met iets.}
   }

   public void run()
   {
    if (TheWork != null)
        while (keepgoing)
        {
          TheWork.execute();
        }
        TheWork.cleanup();
    }
    TheWork = null;
   }

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
The - DDD: Ok, ik ruik... Strategy Pattern.
Hehe ;) .

Op zich wel een aardig pattern, maar ik denk eigenlijk niet dat het in dit geval veel helpt....

Het probleem is dat je een Thread eigenlijk niet bruut mag stoppen. Dit kan je dus alleen doen door interactie met de code die wordt uitgevoerd. Een simpele methode bescheef ik al eerder: maak een request methode en check tijdens het runnen van de thread of je nog door mag gaan.

Als je echter in de code van je Thread geen controle meer hebt over de control flow doordat:

1. De thread wacht op een bepaalde vorm van input (io, ServerSocket en dergelijke).

2. De thread een bepaalde taak moet uitvoeren dmv een extern stuk code wat weleens een flinke tijd zou kunnen gaan duren.

In beide gevallen heb je niet de mogelijkheid om te checken of je nog door mag gaan.

Ik denk dat zelfs een design pattern hier niets aan kan veranderen ;( . Als je denkt dat je toch wat hebt bedacht ben ik erg benieuwd :) . Strategy pattern is wel een aardig pattern maar in feite is het alleen maar een methode waarbij je een interface maakt voor een bepaald algoritme en deze op verschillende kunt gaan implementeren. Eigenlijk zou je zelfs de Runnables van Java in combinatie met een Thread al een Strategy pattern toepassing kunnen noemen... Als je vanuit de lang durende operatie wel de mogelijkheid hebt om via een interface interactie met de context te hebben is je probleem natuurlijk sowieso al opgelost. Het probleem is juist dat die interactie niet mogelijk is...

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
Naar aanleiding van je voorbeeld code:

Dat is inderdaad een aardig ontwerpje, maar je gaat er nu vanuit dat een taak bestaat uit een simpele executies die steeds herhaald wordt. Alleen tussen de executies wordt er gechecked of je nog door mag gaan.

Wat als een executie te lang gaat duren? Hoe stop je je werk dan?

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


  • The - DDD
  • Registratie: Januari 2000
  • Laatst online: 03-09 16:40
Als het goed is moet je met elke methode in java die pas returned na een onbepaalde tijd een timeout kunnen definiëren.

Bijvoorbeeld bij de ServerSocket van Java:

De methode public void setSoTimeout(int timeout)
throws SocketException
Enable/disable SO_TIMEOUT with the specified timeout, in milliseconds. With this option set to a non-zero timeout, a call to accept() for this ServerSocket will block for only this amount of time. If the timeout expires, a java.io.InterruptedIOException is raised, though the ServerSocket is still valid. The option must be enabled prior to entering the blocking operation to have effect. The timeout must be > 0. A timeout of zero is interpreted as an infinite timeout.

Als je ervoor zorgt dat elke blokkeren aanroep een timeout heeft. Dan kun je na elke timeout een bool checken netzolang totdat of de opgevraagde data binnen is, of de vlag voor het stoppen van de thread gezet wordt.
Het vergt wat meer werk, maar het werkt wel.

En vergeet de Interupt niet:
If the
target thread waits for long periods (on a condition variable,
for example), the interrupt method should be used to
interrupt the wait.


Als iets niet een timeout heeft, dan is het wel te interupten. Volgens mij zelfs zo ver dat wanneer je interupt aanroept op een thread, dat ie dan gelijk doorspringt naar de interupt handler. (er wordt een excepotion gegooid en die catch je dan.

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
The - DDD: Als het goed is moet je met elke methode in java die pas returned na een onbepaalde tijd een timeout kunnen definiëren.
Ok, maar dat is natuurlijk een beetje een paarde(n?)middel: time-outs... Bovendien moet hierbij al rekening gehouden met de implementatie van deze mogelijk langdurende methode.

Als een methode hiermee geen rekening heeft gehouden of zelfs gewoon heel erg druk bezig is (zoals in dit geval de parser van Alarmnummer) moet je toch in die code een soort call-backs gaan inbouwen naar de context... Meestal wordt hiermee geen rekening gehouden...

De toepassing van het pattern is dus mooi, maar het lost in dit geval niet echt iets op (behalve dat de code helderder wordt).

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


  • The - DDD
  • Registratie: Januari 2000
  • Laatst online: 03-09 16:40
Uit de java javadoc: [\docs\guide\misc\threadPrimitiveDeprecation.html]
How do I stop a thread that waits for long periods (e.g., for input)?
That's what the Thread.interrupt method is for. The same "state based" signaling mechanism shown above can be used, but the state change (blinker = null, in the previous example) can be followed by a call to Thread.interrupt, to interrupt the wait:

public void stop() {
Thread moribund = waiter;
waiter = null;
moribund.interrupt();
}

For this technique to work, it's critical that any method that catches an interrupt exception and is not prepared to deal with it immediately reasserts the exception. We say reasserts rather than rethrows, because it is not always possible to rethrow the exception. If the method that catches the InterruptedException is not declared to throw this (checked) exception, then it should "reinterrupt itself" with the following incantation:
Thread.currentThread().interrupt();

This ensures that the Thread will reraise the InterruptedException as soon as it is able.

  • The - DDD
  • Registratie: Januari 2000
  • Laatst online: 03-09 16:40
Op zaterdag 24 november 2001 15:56 schreef mbravenboer het volgende:

[..]
Mijn gegeven oplossing is juist heel goed, je moet alleen niet vergeten de interupted exceptions juist af te werken. Ik moest het even opzoeken, maar in mijn stage heb ik iets vergelijkbaars gehad. Het werkt echt perfect. Thread meot stoppen, interupten dat ding. Als je interupt hadlers goed zijn, werkt het echt heel goed.

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
The - DDD: En vergeet de Interupt niet:
Interupt op een thread aanroepen is ook nogal een vrijwillege feature van de code die dan wordt uitgevoerd door een Thread: alleen in speciale gevallen wordt er iets zinvols gedaan, in alle andere gevallen ben je zelf verantwoordelijk voor de afhandeling (en das nu juist het punt ;) )

In de docs van 1.4.0:
public void interrupt():

Interrupts this thread.

First the checkAccess method of this thread is invoked, which may cause a SecurityException to be thrown.

If this thread is waiting, that is, if it is blocked in an invocation of the wait(), wait(long), or wait(long, int) methods of the Object class, then it will receive an InterruptedException.

If this thread is blocked in an I/O operation upon a Channel then the channel will be closed, the thread's interrupt status will be set, and the thread will receive a ClosedByInterruptException.

If this thread is blocked in a Selector then the thread's interrupt status will be set and it will return immediately from the selection operation, possibly with a non-zero value, just as if the selector's wakeup method were invoked.

If none of the previous conditions hold then this thread's interrupt status will be set.
Als de code rekening houdt met interrupts, te interrupteren is of een redelijke manier van time-outs heeft, werkt de oplossing inderdaad keurig.

Het probleem gaat volgens mij echter juist over de vraag wat te doen als dit allemaal niet mogelijk is... en helaas is er dan helemaal niets zinnigs te doen...

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


  • The - DDD
  • Registratie: Januari 2000
  • Laatst online: 03-09 16:40
Er staat ook ergens het volgende: Als een interupt geen effect heeft, dan heeft stop dat ook niet.

En op zich is gegenereerde code wel zo te genereren dat het netjes met interupts omgaat. Alarmnummer moet dus zijn code-generator iets uitbreiden en dan is tie er.

  • The - DDD
  • Registratie: Januari 2000
  • Laatst online: 03-09 16:40
Op vrijdag 23 november 2001 16:17 schreef Alarmnummer het volgende:
Ik heb een vraagje over een ontwerp kwestie over stoppen thread. het Thread.stop() commando is depricated:

This method is inherently unsafe. Stopping a thread with
Thread.stop causes it to unlock all of the monitors that it
has locked (as a natural consequence of the unchecked
ThreadDeath exception propagating up the stack). If
any of the objects previously protected by these monitors were in
an inconsistent state, the damaged objects become visible to
other threads, potentially resulting in arbitrary behavior. Many
uses of stop should be replaced by code that simply
modifies some variable to indicate that the target thread should
stop running. The target thread should check this variable
regularly, and return from its run method in an orderly fashion
if the variable indicates that it is to stop running. If the
target thread waits for long periods (on a condition variable,
for example), the interrupt method should be used to
interrupt the wait.


Oke, dit snap ik :) Maar stel dat niet de mogelijkheid heb om in de run methode te gaan kijken naar die variable? Bijvoorbeeld: ik roep een tijdsconsumerende routine aan in een api (in mijn geval in een gegenereerde routine) en daar kan ik niet kijken naar die variable (omdat de source elke keer gegenereerd wordt of omdat je geen toegang tot de source hebt). Hoe zou ik dit probleem moeten fixen?
Ik zie nu ook dat het antwoord al recht voor de neus van Alarmnummer stond :+

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
The - DDD: Mijn gegeven oplossing is juist heel goed
Als de code aan bepaalde voorwaarden werkt het ook inderdaad heel erg goed, maar als ik het goed begrepen heb doet de interrupt methode alleen onder bepaalde voorwaarden iets nuttigs (In monitoren, channels e.d.). Het bruut afbreken van een methode executie is gewoon te gevaarlijk om het uberhaupt mogelijk te maken... Er moeten dus voorzieningen zijn (wat jij in feite ook zegt).

Doug Lea behandelt dit probleem ook in "Concurrent Programming in Java, Second Edition. Design Principles and Patterns" (tip!).

It is humanly impossible to write all methods in ways that allow a cancellation exception to occur at every bytecode. (3.1.2.3)

Ook heeft hij het uiteraard over interrupten van een Thread (3.1.2.1): Thread interrupts serve as requests that activities be cancelled. Interrupt based cancellation relies on a protocol between cancellers and cancellees to ensure that objects [...] do not become damaged when cancelled threads terminate. Most classes in the java.* packages conform to this protocol [...] There is noting about interrupt that forces immediate termination.

Hij noemt als mogelijke reacties: continuation (doorgaan ;) ), abrupt termination (error), roll-back en roll-forward.

Thread.join, sleep en Object.wait checken automatisch of een thread isInterrupted. Daarom moet je daar ook de InterruptedException opvangen. Het is verder aan jou om te beslissen wat je daarmee wilt doen.... Op andere punten waar je zou moeten checken of je moet stoppen, moet je dit toch echt zelf gaan controleren...
En op zich is gegenereerde code wel zo te genereren dat het netjes met interupts omgaat
Uiteraard, maar het ging bijvoorbeeld ook om code waar je geen invloed op hebt...

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


  • The - DDD
  • Registratie: Januari 2000
  • Laatst online: 03-09 16:40
Hmm inderdaad, als je totaal een invloed en inzicht hebt op de code die je uit moet voeren. (iets wat mij zeer sterk lijkt overigens)

Dan is het inderdaad het beste om dit in te pakken in een andere thread. En vanuit een andere thread op respons, afloop, terugkoppeling, etc. te wachten.

Ik denk wel dat we Alarmnummer de mogelijkheden nu uiteen hebben gezet en hij zodoende de best passende oplossing kan pakken en proberen te implementeren. Toch? ;)

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
The - DDD: iets wat mij zeer sterk lijkt overigens
Inderdaad, meestal moet er toch wel iets te regelen zijn, zeker als je zelf de source-code genereert en dus in de hand hebt.
Ik denk wel dat we Alarmnummer de mogelijkheden nu uiteen hebben gezet en hij zodoende de best passende oplossing kan pakken en proberen te implementeren. Toch? ;)
Lijkt mij ook ;) .

Dat boek wat ik noemde is trouwens erg leuk. Het behandeld dus concurrent programming, maar dan meer uit een patterns georienteerde aanpak. Erg leuk om te lezen als je geintereseerd bent in design-patterns en architectuur... Helaas heb ik nog geen tijd gehad om het echt goed te bestuderen ;( . Doug Lea rules ;) .

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


  • The - DDD
  • Registratie: Januari 2000
  • Laatst online: 03-09 16:40
Laat ik eerst maar het boek van The Gang Of Four doorgelezen hebben.

Best wel bruut wat ik door moet werken deze periode...

Boek van de GoF.
Win32 boek van Richter.
Win32 boek van Petzold.
En intussen nog een zelfstudie opdracht OpenGL.

Druk druk druk... :P

En daarna een stage. Ben benieuwd bij welk bedrijf ik binnen kan komen. Er ontwikkelen zich al een aantal mogelijkheden.

Wie weet kom ik aan dat concurrent programming boek toe tijdens mijn stage. :)
Ik hoor trouwens van alle kanten dat de boeken uit de Java serie van Sun erg goed zijn.

Lekker makkelijk die linkjes naar amazon:
code:
1
http://www.amazon.com/exec/obidos/ASIN/[isbn nummer zonder "-", maar wel met Xjes.]

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
The - DDD: The Gang Of Four, links, OpenGL
Je bent er maar druk mee ;) .
En daarna een stage. Ben benieuwd bij welk bedrijf ik binnen kan komen. Er ontwikkelen zich al een aantal mogelijkheden.
<nieuwsgiering> In welke richting? </nieuwsgiering>
Wie weet kom ik aan dat concurrent programming boek toe tijdens mijn stage. :)
Onthoud het in ieder geval :) . Het bevalt mij erg goed. Leuke toepassing van patterns in de threaded stuff.

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


  • The - DDD
  • Registratie: Januari 2000
  • Laatst online: 03-09 16:40
Toch wel de richting Java.

Heb er m'n derde jaars stage ook mee vervuld. (HBO HI)
De eisen die ik op dit moment aan mijn stage heb zijn redelijk open:

-Graag samen moeten werken met anderen (was in mijn vorige stage niet zo)
-Indien mogelijk Java en CBD.
-Precieze inhoudt ben ik nog niet aan toe, moet immers pas op 2 februari beginnen met mijn stage. Oh ja, het betreft een afstudeerstage.

Wat betreft de bedrijven: Als ze maar echte kennis in huis hebben, niet een zooitje hobbyisten bij elkaar die door zelf studie programmeren hebben geleerd. Ik zoek gestructureerde aanpak in het bedrijf van mijn keuze. OO op een nette manier (dus met UML en dergelijke).

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
Als je Groningen niet erg vind, dan kan ik misschien wel een afstudeer plek voor je regelen.

inhoud:
expertsystemen voor de RuG (Rijks Universiteit Groningen) (oa rulebased semantisch oplossend expertsysteem) wat als redeneer systeem draaid voor automatisering wetgeving. En binnenkort gaan we dit gebruiken voor een intelligent agent systeem waarbij belangrijke databases (politie,belasting,gemeente etc) open worden gesteld en mbv gatekeepers (servers die draaien voor de db zodat niet iedereen er op kan) en agents moet een andere agent info kunnen vinden. Als je dit iets lijkt moet je me even een mailtje sturen. Ik heb er zelf mijn afstudeer opdracht ook gedaan, en het is me uitstekend bevallen (werk er nu zelfs :) )

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
Alarmnummer: expertsystemen
Trouwens, jij bent altijd aardig druk met dat expersysteem, dus je zult ook wel wat van die stuff afweten: ken je Peter Lucas?

Ik heb les van hem gehad op de UU. Hij heeft een behoorlijk goed boek geschreven over expert-systemen. Voor dat vak heb ik toen als practicum nog eens een expert-systeem core gemaakt in Java. Het design was volledig object-georienteerd... Werkte wel grappig :) .

Ik heb altijd de neiging om zulke zogenaamde AI zaken niet in die vage AI taaltje te gaan doen ;) . Mijn vriendin moest een keer wat vrij ingewikkelds maken met stelling-bewijzers en semantische-tableau's en al dat gebla. Dat hebben we toen samen ook in Java gemaakt ipv Prolog ;) . Nu ik echter Stratego heb gezien zou ik het toch maar daarin maken... Een programma-transformatie taal ingezet als AI... AI is eigenlijk best dom ;) .

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment

Pagina: 1