Heim  >  Artikel  >  Java  >  Einführung in die Verwendung der ReentrantLock-Klasse in

Einführung in die Verwendung der ReentrantLock-Klasse in

不言
不言nach vorne
2019-03-30 10:40:282511Durchsuche

Dieser Artikel bietet Ihnen eine Einführung in die Verwendung der ReentrantLock-Klasse in Java. Ich hoffe, dass er für Freunde hilfreich ist.

Im Java-Multithreading können Sie das synchronisierte Schlüsselwort verwenden, um Synchronisierung und gegenseitigen Ausschluss zwischen mehreren Threads zu erreichen. Die in JDK 1.5 hinzugefügte neue ReentrantLock-Klasse kann jedoch auch den gleichen Effekt erzielen und verfügt außerdem über erweiterte Funktionen. Leistungsstärker, z. B. Sniffing-Sperren, Mehrwege-Zweigbenachrichtigungen, faire Sperren und unfaire Sperren (Standard)-Funktionen, und flexibler in der Verwendung als synchronisiert.

Verwenden Sie ReentrantLock, um eine Synchronisierung zu erreichen

public class MyService {
    private Lock lock = new ReentrantLock();
    public void testMethod() {
        lock.lock();
        for (int i = 0; i < 10; i++){
            System.out.println("ThreadName=" + Thread.currentThread().getName() + (" " + (i + 1)));
        }
        lock.unlock();
    }
}
public class MyThread extends Thread {
    private MyService myService;
    public MyThread(MyService myService) {
        this.myService = myService;
    }
    @Override
    public void run() {
        myService.testMethod();
    }
}
public static void main(String[] args) throws IOException, InterruptedException {
MyService myService = new MyService();
MyThread myThreadA = new MyThread(myService);
        MyThread myThreadB = new MyThread(myService);
        MyThread myThreadC = new MyThread(myService);
        MyThread myThreadD = new MyThread(myService);
        MyThread myThreadE = new MyThread(myService);

        myThreadA.start();
        myThreadB.start();
        myThreadC.start();
        myThreadD.start();
        myThreadE.start();

    }

Rufen Sie die lock()-Methode des ReentrantLock-Objekts auf, um die Sperre zu erhalten, und rufen Sie die unLock()-Methode auf, um die Sperre aufzuheben.

Den laufenden Ergebnissen nach zu urteilen, wird die Sperre aufgehoben Nachdem der aktuelle Thread mit dem Drucken fertig ist, können andere Threads mit dem Drucken fortfahren, da der aktuelle Thread bereits die Sperre hält, die Reihenfolge des Druckens zwischen den Threads jedoch zufällig ist.

Bedingung zum Implementieren von Warten/Benachrichtigung verwenden

Das Schlüsselwort „synced“ kann mit den Methoden „wait()“ und „notify()“ / „notifyall()“ kombiniert werden, um den Warte-/Benachrichtigungsmodus zu implementieren ()-Methode aufgerufen wird, wählt die JVM zufällig einen Thread im WAITNG-Status zur Ausführung aus.

Die Verwendung von Condition kann flexibler sein, Sie können eine „selektive Benachrichtigung“ implementieren und angeben, welche Threads aktiviert werden sollen und welche Threads weiter warten sollen.

public class MyService {

    private Lock lock = new ReentrantLock();
    public Condition conditionA = lock.newCondition();
    public Condition conditionB = lock.newCondition();

    public void awaitA() throws InterruptedException {
        lock.lock();

        System.out.println("begin awaitA 时间" + System.currentTimeMillis() + "ThreadName=" + Thread.currentThread().getName());

        conditionA.await();

        System.out.println("end awaitA 时间" + System.currentTimeMillis() + "ThreadName=" + Thread.currentThread().getName());

        lock.unlock();
    }

    public void awaitB() throws InterruptedException {
        lock.lock();

        System.out.println("begin awaitB 时间" + System.currentTimeMillis() + "ThreadName=" + Thread.currentThread().getName());

        conditionB.await();

        System.out.println("end awaitB 时间" + System.currentTimeMillis() + "ThreadName=" + Thread.currentThread().getName());

        lock.unlock();
    }

    public void  signalAll_A() throws InterruptedException {
        lock.lock();
        System.out.println("begin signalAll_A 时间" + System.currentTimeMillis() + "ThreadName=" + Thread.currentThread().getName());

        conditionA.signalAll();

        lock.unlock();
    }

    public void  signalAll_B() throws InterruptedException {
        lock.lock();
        System.out.println("begin signalAll_B 时间" + System.currentTimeMillis() + "ThreadName=" + Thread.currentThread().getName());

        conditionB.signalAll();

        lock.unlock();
    }
}
public class ThreadA extends Thread {

    private MyService myService;
    public ThreadA(MyService myService) {
        this.myService = myService;
    }

    @Override
    public void run() {
        try {
            myService.awaitA();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
public class ThreadB extends Thread {

    private MyService myService;

    public ThreadB(MyService myService) {
        this.myService = myService;
    }

    @Override
    public void run() {
        try {
            myService.awaitB();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
    public static void main(String[] args) throws IOException, InterruptedException {

        MyService myService = new MyService();

        ThreadA threadA = new ThreadA(myService);
        threadA.setName("a");
        threadA.start();

        ThreadB threadB = new ThreadB(myService);
        threadB.setName("b");
        threadB.start();

        Thread.sleep(3000);
        myService.signalAll_A();

    }
  • In der Object-Klasse ist die Methode wait() äquivalent zur Methode waiting() in der Klasse Condition.
  • Das wait(long timeout )-Methode in der Object-Klasse entspricht derawait(long time, TimeUnit-Einheit)-Methode in der Condition-Klasse.
  • Die notify()-Methode in der Object-Klasse entspricht der signal()-Methode in der Condition Klasse.
  • Die notifyAll()-Methode in der Object-Klasse entspricht der signalAll()-Methode in der Condition-Klasse.

Nach den Ausführungsergebnissen zu urteilen, sind die Threads a und b angehalten. Wenn die Methode myService.signalAll_A() ausgeführt wird, wird Thread a weiterhin ausgeführt, während sich Thread b noch im Wartezustand befindet.

Gemeinsame Methoden

ReentrantLock-Klasse

int getHoldCount() fragt die Anzahl der Aufrufe der lock()-Methode ab.

final int getQueueLength() schätzt die Anzahl der Threads, die auf die Sperre warten. Beispielsweise gibt es 5 Threads, 1 Thread zuerst Führt die Methode „await()“ aus, dann ist der Rückgabewert nach dem Aufruf dieser Methode 4, was darauf hinweist, dass 4 Threads gleichzeitig auf die Freigabe der Sperre warten.

int getWaitQueueLength(Condition condition) gibt dasselbe zurück als diese Sperre Eine Schätzung der Anzahl der Threads, die auf eine bestimmte Bedingung warten. Wenn beispielsweise 5 Threads vorhanden sind und jeder Thread die Methode „await()“ desselben Bedingungsobjekts ausführt, ist der beim Aufruf dieser Methode zurückgegebene Wert 5.

final boolean hasQueuedThreads() bestimmt, ob Threads auf diese Sperre warten.

final boolean hasQueuedThread(Thread thread) bestimmt, ob der angegebene Thread darauf wartet, diese Sperre zu erhalten.

boolean hasWaiters(Condition condition) bestimmt den Thread. Haben Sie die Methode waiting() aufgerufen?

void lockInterruptably() löst eine InterruptedException aus, um die Sperre zu erhalten, es sei denn, der aktuelle Thread wird unterbrochen.

Bedingungsklasse

void waitingUninterruptably() und waiting( ) Der Unterschied besteht darin, dass die InterrputedException-Ausnahme nicht ausgelöst wird, wenn die Interrupt()-Methode aufgerufen wird.

Dieser Artikel ist hier vollständig Weitere spannende Inhalte finden Sie im Java-Video in der Tutorial-Spalte auf der chinesischen PHP-Website!

Das obige ist der detaillierte Inhalt vonEinführung in die Verwendung der ReentrantLock-Klasse in. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:segmentfault.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen