2017-02-12 3 views
1

Ich kenne einige Details in Bezug auf AbstractQueuedSynchronizer. Es ist ein Framework zum Erstellen von zustandsabhängigen Klassen oder Synchronizer. Aber ich habe nicht den Sinn, diese Klasse in Worker von ThreadPoolExecutor zu erweitern.

  1. Wenn eine neue Runnable/Callable Aufgabe erstellt wird, ein neues Worker Objekt vorgelegt:

    private final class Worker extends AbstractQueuedSynchronizer implements Runnable 
    

    Wie folgenden Dinge durch die Unterschrift der Arbeiterklasse gesehen abgeleitet werden.

  2. Ein neues Objekt von Worker kann als neuer Thread betrachtet werden.

  3. addWorker() Methode wird neue Worker (oder einfach eine Aufgabe) hinzufügen und ruft worker.start() auf, um den Thread zu starten.

  4. Arbeiterklasse ist nicht statische geschachtelte Klasse, daher kann es alle Variablen von ThreadPoolExecutor Zugriff

  5. run() Methode der Arbeiterklasse ruft intern runWorker (this)

    public void run() { runWorker (Dies); }

  6. runWorker() führt die eigentliche Aufgabe etwas wie folgt:

    void runWorker(Worker w) { try { w.lock(); w.firstTask.run() } finally { w.unlock(); } }

AQS nur für diese Sperre verwendet wird und Entsperren von runWorker() Methode. Können wir nicht ein ReentrantLock hier nehmen und Arbeiterklasse einfach halten?

auch Klasse bieten Dokumentation in Bezug auf diese, aber ich bin nicht in der Lage, das verstehen:

Diese Klasse erweitert opportunistisch AbstractQueuedSynchronizer zu vereinfachen Erwerb und die Freigabe einer Sperre jeder Aufgabe umgebenden Ausführung. Dies schützt vor Interrupts, die dazu gedacht sind, aufzuwachen, während ein Worker-Thread, der auf eine Task wartet, statt einer Task gerade ausgeführt wird. Wir implementieren eine einfache non-reentrant wechselseitige Ausschlusssperre statt ReentrantLock zu verwenden, da wir nicht möchten, dass Worker Tasks die Sperre erneut abrufen können, wenn sie Poolsteuermethoden wie SetCorePoolSize aufrufen.

Bitte helfen ist

Antwort

2

Antwort auf Ihre Frage in dem Zitat von javadoc die Ihr geschrieben:

Wir implementieren eine einfache nichtablaufinvarianten gegenseitigen Exklusionssperre statt Verwendung ReentrantLock, weil wir tun nicht wollen, dass Worker Tasks die Sperre wiedererlangen können, wenn sie Poolsteuerungsmethoden wie setCorePoolSize aufrufen.

Das ist, weil Threads, die für Aufgaben warten können angezeigt werden durch nicht gesperrt werden, das heißt tryLock kehrt true für sie. Und was in diesem Fall passieren könnte, wenn ReentrantLock wird hier verwendet wird: dann wird es möglich sein, folgende Sequenz von Aktionen: (! Hier Erfolg)

setCorePoolSize - ->interruptIdleWorkers>tryLock() ->Thread.interrupt (Faden dieses Arbeitnehmers)

die Arbeiter Interrupt selbst verursachen.

Verwandte Themen