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