2010-11-30 11 views
2

Ich habe eine Methode, sagen wir method1(), das dauert eine Weile zu laufen. Wenn während der Ausführung ein anderer Aufruf von method1() erfolgt, sollte dieser ignoriert werden. Ich habe ungefähr so ​​etwas wie diesesGibt es einen alternativen/besseren Weg, um diese einfache Logik in Java zu machen?

boolean mFlag = false; 

    void method1() 
    { 
     if(!mFlag) 
     { 
      mFlag=true; 

      // do Stuff 

      mFlag=false; 
     } 
    } 

Dies funktioniert. Aber ich habe mich gefragt, ob es einen besseren Weg gibt, dies zu tun, möglichst ohne Flaggen.

+1

Das ist gut. So wird es normalerweise gemacht. –

+1

Versuchen Sie, das Problem zu lösen, dass mehrere Threads dieselbe Methode auf einmal ausführen, oder das Problem der Methode (vielleicht indirekt) sich selbst nennt? –

+1

@Anon die Methode, die sich indirekt aufruft. –

Antwort

6

Ja, sollten Sie wirklich etwas von java.util.concurrent.locks verwenden werden Ihr Beispiel recht ist nicht ganz korrekt, muss die boolean volatil sein .

Bearbeitet, um das Überspringen der Ausführung bei Wiedereintritt zu behandeln, wie in Ihrem Kommentar angegeben. Leider gibt es nicht wirklich eine gute Möglichkeit, das mit der eingebauten Bibliothek zu tun, da es ein etwas seltsamer Anwendungsfall ist, aber ich denke immer noch, dass die Verwendung der eingebauten Bibliothek eine bessere Option ist.

0

Vielleicht sollten Sie synchronisierte Methoden verwenden

http://download.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html

+2

mein Verständnis ist, dass mit synchronisierten Methoden, der zweite Anruf blockiert wäre, bis der erste Anruf abgeschlossen ist und dann ausführen zweiter Anruf. aber meine Anforderung ist, dass der zweite Anruf ignoriert wird. –

+1

@Bala: das ist richtig. Sie müssten synchronisieren, während Sie Ihre Flagge wie oben setzen. Sie müssten auch eine doppelte Sperrung durchführen: http://en.wikipedia.org/wiki/Double-checked_locking Die Art, wie Sie es oben haben, wäre anfällig für Synchronisationsprobleme beim Setzen und Überprüfen des Flags. Oder ... Sie können die Lock-Klasse wie Affe vorgeschlagen verwenden. :) –

+1

@Bala - gegeben, was Sie in den Kommentaren zu Ihrer Frage sagen, beachten Sie bitte, dass ein zweiter Anruf * aus einem anderen Thread * blockiert wäre. Wenn Ihre Methode rekursiv (direkt oder indirekt) vom selben Thread aufgerufen wurde, blockierte der zweite Aufruf * aus dem gleichen Thread * nicht *. –

1

Sie versuchen, sich vor dem Wiedereintritt von demselben Thread oder mehreren Threads zu schützen, die gleichzeitig zugreifen.

Unter der Annahme eines Multi-Thread-Zugriffs ist der Lichtansatz java.util.concurrent.atomic zu verwenden. Keine Notwendigkeit für etwas, das so schwer ist wie ein Schloss (vorausgesetzt, es gibt keine weiteren Anforderungen).

no-Reentry aus der gleichen Methode Unter der Annahme:

private final AtomicBoolean inMethod = new AtomicBoolean(); 

void method1() { 
    if (inMethod.compareAndSet(true, false)) { // Alternatively getAndSet 
     try { 
      // do Stuff 
     } finally { 
      inMethod.set(false); // Need to cover exception case! 
     } 
    } 
} 

Wenn Sie Reentry im selben Thread zulassen wollen, dann wird es chaotisch genug Schlösser zu verwenden:

private final AtomicReference<Thread> inMethod = new AtomicReference<Thread>(); 

void method1() { 
    final Thread current = Thread.currentThread(); 
    final Thread old = inMethod.get(); 
    if (
     old == current || // We already have it. 
     inMethod.compareAndSet(null, current) // Acquired it. 
    ) { 
     try { 
      // do Stuff 
     } finally { 
      inMethod.set(old); // Could optimise for no change. 
     } 
    } 
} 

könnte die Verwendung Execute Around Idiom dafür.

Verwandte Themen