Maison  >  Article  >  Java  >  Introduction à l'utilisation de la classe ReentrantLock dans

Introduction à l'utilisation de la classe ReentrantLock dans

不言
不言avant
2019-03-30 10:40:282520parcourir

Cet article vous présente une introduction à l'utilisation de la classe ReentrantLock en Java. Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer.

En Java multi-threading, vous pouvez utiliser le mot-clé synchronisé pour obtenir la synchronisation et l'exclusion mutuelle entre plusieurs threads, mais la nouvelle classe ReentrantLock ajoutée dans JDK 1.5 peut également obtenir le même effet et possède également des fonctions étendues. Plus puissant, comme les verrous reniflants, les notifications de branches multidirectionnelles, les fonctions de verrouillage équitable et de verrouillage injuste (par défaut), et plus flexible à utiliser que synchronisé.

Utilisez ReentrantLock pour réaliser la synchronisation

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();

    }

Appelez la méthode lock() de l'objet ReentrantLock pour acquérir le verrou, et appelez la méthode unLock() pour libérer le verrou.

Depuis l'exécution résultats, actuellement Une fois l'impression du thread terminée, le verrou est libéré et les autres threads peuvent continuer à imprimer. Les données imprimées par le thread sont imprimées en groupes, car le thread actuel détient déjà le verrou, mais l'ordre d'impression entre les threads est aléatoire. .

Utiliser Condition pour implémenter l'attente/notification

Le mot-clé synchronisé est combiné avec les méthodes wait() et notify()/notifyall() pour implémenter le mode d'attente/notification, mais lorsqu'il est utilisé, le mode d'attente/notification est utilisé. JVM appellera aléatoirement la méthode notify() Sélectionnez un thread dans l'état WAITNG à exécuter.

L'utilisation de Condition peut être plus flexible, vous pouvez implémenter une "notification sélective", et vous pouvez spécifier quels threads réveiller et quels threads continuer à attendre.

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();

    }
  • La méthode wait() de la classe Object est équivalente à la méthode wait() de la classe Condition.
  • La méthode wait(long timeout) dans la classe Object Équivalent à la méthode wait(long time, TimeUnit unit) dans la classe Condition La méthode notify() dans la classe
  • Object est équivalente. à la méthode signal() dans la classe Condition.
  • Dans la classe Object La méthode notifyAll() est équivalente à la méthode signalAll() dans la classe Condition

De la. Résultats de l'exécution, les threads a et b sont suspendus. Lorsque la méthode myService.signalAll_A() est exécutée, le thread a continue l'exécution, tandis que le thread b est toujours en état d'attente.

Méthodes communes

Classe ReentrantLock

int getHoldCount() interroge le nombre de fois que la méthode lock() est appelée.

final int getQueueLength() estime le nombre de threads en attente du verrou Par exemple. , il y a 5 threads, et 1 thread exécute d'abord la méthode wait(), puis la valeur de retour après avoir appelé cette méthode est 4, indiquant que 4 threads attendent le verrou en même temps.

. int getWaitQueueLength(Condition condition) Renvoie une estimation du nombre de threads en attente d'une condition donnée associée à ce verrou. Par exemple, il y a 5 threads, et chaque thread exécute la méthode wait() du même objet de condition, la valeur renvoyée lors de l'appel. cette méthode est 5.

final boolean hasQueuedThreads() détermine s'il y a des threads en attente de ce verrou.

final boolean hasQueuedThread(Thread thread) détermine si le thread spécifié attend pour acquérir ce verrou.

boolean hasWaiters(Condition condition) Déterminez si le thread a appelé la méthode wait().

void lockInterruptably() lance InterruptedException pour acquérir le verrou, à moins que le thread actuel ne soit interrompu.

Classe de condition

La différence entre void waitUninterruptably() et wait() est que l'exception InterrputedException ne sera pas levée lorsque la méthode interrompu() est appelée.

Cet article est tout ici, c'est fini. Pour plus d'autres contenus passionnants, vous pouvez faire attention à la colonne Java Video Tutorial du site Web PHP chinois !

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer