2010-07-02 5 views
9

Ich verwende die CountDownLatch, um einen Initialisierungsprozess zwischen zwei Threads zu synchronisieren, und ich frage mich über die ordnungsgemäße Handhabung der InterruptedException, die es werfen könnte.CountDownLatch InterruptedException

der Code war ich anfangs dieses schrieb:

private CountDownLatch initWaitHandle = new CountDownLatch(1); 
    /** 
    * This method will block until the thread has fully initialized, this should only be called from different threads Ensure that the thread has started before this is called. 
    */ 
    public void ensureInitialized() 
    { 
     assert this.isAlive() : "The thread should be started before calling this method."; 
     assert Thread.currentThread() != this, "This should be called from a different thread (potential deadlock)"; 
     while(true) 
     { 
      try 
      { 
       //we wait until the updater thread initializes the cache 
       //that way we know 
       initWaitHandle.await(); 
       break;//if we get here the latch is zero and we are done 
      } 
      catch (InterruptedException e) 
      { 
       LOG.warn("Thread interrupted", e); 
      } 
     } 
    } 

Ist dieses Muster einen Sinn? Grundsätzlich ist es eine gute Idee, die InterruptedException ignorieren nur warten, bis es erfolgreich ist. Ich glaube, ich verstehe einfach nicht die Situationen, in denen dies unterbrochen werden würde, also weiß ich nicht, ob ich anders damit umgehen sollte.

Warum wird hier eine InterruptedException ausgelöst, welche Vorgehensweise ist am besten geeignet?

Antwort

9

Dies ist genau das, was Sie für eine InterruptedException nicht tun sollten. Eine InterruptedException ist im Grunde eine höfliche Anfrage für diesen Thread zu beenden. Der Faden sollte so schnell wie möglich aufräumen und austreten.

IBM hat einen guten Artikel darüber geschrieben: http://www.ibm.com/developerworks/java/library/j-jtp05236.html

Hier ist, was ich tun würde:

// Run while not interrupted. 
while(!(Thread.interrupted()) 
{ 
    try 
    { 
     // Do whatever here. 
    } 
    catch(InterruptedException e) 
    { 
     // This will cause the current thread's interrupt flag to be set. 
     Thread.currentThread().interrupt(); 
    } 
} 

// Perform cleanup and exit thread. 

Der Vorteil es auf diese Weise tun, ist so: Wenn der Faden während in einer Sperr unterbrochen Methode wird das Interrupt-Bit nicht gesetzt und stattdessen wird InterruptedException geworfen. Wenn Ihr Thread unterbrochen wird, während Sie nicht in einer Blockierungsmethode sind, wird das unterbrochene Bit festgelegt, und es wird keine Ausnahme ausgelöst. Durch Aufrufen von interrupt(), um das Flag für eine Ausnahme festzulegen, werden beide Fälle auf den ersten Fall normalisiert, der dann von der Schleifenbedingung überprüft wird.

Als zusätzlichen Bonus können Sie damit Ihren Thread stoppen, indem Sie ihn einfach unterbrechen, anstatt einen eigenen Mechanismus oder eine eigene Schnittstelle zu erfinden, um ein boolesches Flag zu setzen, um genau dasselbe zu tun.

+0

Gah Ich habe versucht, Ihre Formatierung zu beheben, und es hat einen Bearbeitungskonflikt. Ich habe keine Möglichkeit zurückzurollen. Es tut uns leid! –

+0

Ich rollte es schon zurück. Danke für die Hilfe! Ich hatte es falsch bemerkt, aber beschlossen, es gleichzeitig mit dem Schreiben der Textwand zu reparieren. – jdmichal

+0

Eigentlich nein, ich bin nur wirklich an Wikipedia gewöhnt, wo Sie auf die Änderung, die Sie rückgängig machen möchten, auf Rollback klicken, nicht auf die Revision, die Sie zurücksetzen möchten ** zu **. –

2

Wenn Sie keinen legitimen Grund voraussehen, dass die Thread unterbrochen werden konnte und kann von jeder angemessenen Reaktion auf sie nicht denken, würde ich sagen, Sie

catch (InterruptedException e){ 
     throw new AssertionError("Unexpected Interruption",e); 
} 

auf diese Weise die Anwendung tun sollte, wird wenn eine solche Unterbrechung auftritt, kann dies eindeutig fehlschlagen, was es einfacher macht, während des Tests zu entdecken. Dann können Sie darüber nachdenken, wie die Anwendung damit umgehen soll, oder ob es sich um ein Problem im Design handelt.

Verwandte Themen