溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

jdk中ReentrantLock類與Condition類結合的使用方法

發布時間:2021-07-13 09:07:04 來源:億速云 閱讀:149 作者:chen 欄目:大數據

本篇內容主要講解“jdk中ReentrantLock類與Condition類結合的使用方法”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“jdk中ReentrantLock類與Condition類結合的使用方法”吧!

我們在上一篇簡單介紹了ReentrantLock類的基本使用,也就是獲取鎖,與釋放鎖。那如果我們要實現wait()和notify()等待通知的功能在ReentrantLock類中我們應該怎么辦呢。這時我們就要借助一個新類了,它就是Condition類。Condition類也是JDK1.5以后新增的類。它可以實現多路通知功能,也就是說在一個Lock對象中可以創建多個Condition類相當于有多個鎖對象,通知的時候可以選擇性的進行線程通知,而不是notify()那樣是由CPU隨機決定通知的是哪個線程,Condition類使它在線程調度上更加靈活。下面我們看一下具體的事例。

/**
* 用戶登錄
*
* @author Sama
* @author admin@jilinwula.com
* @date 2017-03-15 10:35
* @since 1.0.0
*/
public class Userinfo {

   private Lock lock = new ReentrantLock();
   private Condition condition = lock.newCondition();

   public void await() {
       try {
           lock.lock();
           System.out.println(String.format("線程開始\tthread: %s", Thread.currentThread().getName()));
           condition.await();
           System.out.println(String.format("線程結束\tthread: %s", Thread.currentThread().getName()));
       } catch (InterruptedException e) {
           e.printStackTrace();
       } finally {
           lock.unlock();
       }
   }

   public void signal() {
       lock.lock();
       System.out.println(String.format("線程恢復\tthread: %s", Thread.currentThread().getName()));
       condition.signal();
       lock.unlock();
   }
}
/**
* 管理用戶請求
*
* @author Sama
* @author admin@jilinwula.com
* @date 2017-03-15 10:44
* @since 1.0.0
*/
public class RequestAdmin extends Thread {

   private Userinfo userinfo;


   public RequestAdmin(Userinfo userinfo) {
       this.userinfo = userinfo;
   }

   @Override
   public void run() {
       userinfo.await();
   }
}
/**
* 用戶請求
*
* @author Sama
* @author admin@jilinwula.com
* @date 2017-03-15 10:44
* @since 1.0.0
*/
public class RequestUser extends Thread {

   private Userinfo userinfo;

   public RequestUser(Userinfo userinfo) {
       this.userinfo = userinfo;
   }

   @Override
   public void run() {
       userinfo.signal();
   }
}
/**
* @author Sama
* @author admin@jilinwula.com
* @date 2017-03-20 13:35
* @since 1.0.0
*/
public class Test {
   public static void main(String[] args) throws InterruptedException {
       Userinfo userinfo = new Userinfo();
       RequestAdmin requestAdmin = new RequestAdmin(userinfo);
       RequestUser requestUser = new RequestUser(userinfo);
       requestAdmin.start();
       Thread.sleep(1000);
       for (int i = 3; i > 0; i--) {
           System.out.println(String.format("倒計時:%s", i));
           Thread.sleep(1000);
       }
       requestUser.start();
   }
}
線程開始	thread: Thread-0
倒計時:3
倒計時:2
倒計時:1
線程恢復 thread: Thread-1
線程結束 thread: Thread-0

我們用ReentrantLock和Condition類成功實現了wait()和notify()暫停與通知的功能。使用還是比較簡單,和以前的wait()、notify()方法使用基本一致。

condition.await(); // 相當于wait()方法
condition.signal();// 相當于notify()方法

我們知道用notifyAll()方法可以恢復暫停的所有線程,同樣Condition類中也有同樣的方法實現了該邏輯,只是方法不叫notifyAll()而是叫signalAll()方法。請看下面事例。

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
* 用戶登錄
*
* @author Sama
* @author admin@jilinwula.com
* @date 2017-03-15 10:35
* @since 1.0.0
*/
public class Userinfo {

   private Lock lock = new ReentrantLock();
   private Condition condition = lock.newCondition();

   public void await1() {
       try {
           lock.lock();
           System.out.println(String.format("await1線程開始\tthread: %s", Thread.currentThread().getName()));
           condition.await();
           System.out.println(String.format("await1線程結束\tthread: %s", Thread.currentThread().getName()));
       } catch (InterruptedException e) {
           e.printStackTrace();
       } finally {
           lock.unlock();
       }
   }

   public void await2() {
       try {
           lock.lock();
           System.out.println(String.format("await2線程開始\tthread: %s", Thread.currentThread().getName()));
           condition.await();
           System.out.println(String.format("await2線程結束\tthread: %s", Thread.currentThread().getName()));
       } catch (InterruptedException e) {
           e.printStackTrace();
       } finally {
           lock.unlock();
       }
   }

   public void signalAll() {
       lock.lock();
       System.out.println(String.format("恢復所有線程\tthread: %s", Thread.currentThread().getName()));
       condition.signalAll();
       lock.unlock();
   }
}
/**
* 管理用戶請求
*
* @author Sama
* @author admin@jilinwula.com
* @date 2017-03-15 10:44
* @since 1.0.0
*/
public class RequestAdmin extends Thread {

   private Userinfo userinfo;


   public RequestAdmin(Userinfo userinfo) {
       this.userinfo = userinfo;
   }

   @Override
   public void run() {
       userinfo.await1();
   }
}
/**
* 用戶請求
*
* @author Sama
* @author admin@jilinwula.com
* @date 2017-03-15 10:44
* @since 1.0.0
*/
public class RequestUser extends Thread {

   private Userinfo userinfo;

   public RequestUser(Userinfo userinfo) {
       this.userinfo = userinfo;
   }

   @Override
   public void run() {
       userinfo.await2();
   }
}
/**
* @author Sama
* @author admin@jilinwula.com
* @date 2017-03-20 13:35
* @since 1.0.0
*/
public class Test {
   public static void main(String[] args) throws InterruptedException {
       Userinfo userinfo = new Userinfo();
       RequestAdmin requestAdmin = new RequestAdmin(userinfo);
       RequestUser requestUser = new RequestUser(userinfo);
       requestAdmin.start();
       requestUser.start();
       Thread.sleep(1000);
       for (int i = 3; i > 0; i--) {
           System.out.println(String.format("倒計時:%s", i));
           Thread.sleep(1000);
       }
       userinfo.signalAll();
   }
}
await1線程開始	thread: Thread-0
await2線程開始 thread: Thread-1
倒計時:3
倒計時:2
倒計時:1
恢復所有線程 thread: main
await1線程結束 thread: Thread-0
await2線程結束 thread: Thread-1

我們看因為調用了signalAll()方法,所以所有暫停的線程都被恢復了。這和notifyAll()方法一樣,沒什么好說的。但如果我們想要實現恢復指定的線程那應該怎么辦呢?我們知道調用notifyAll()方法恢復哪個線程是由CPU決定的,我們程序是控制不了的,這時有人可能會想到設置線程的優先級來實現讓指定的線程優先執行。但這還不是絕對的。設置優先級也是說明那個線程獲取執行的概率比較大,還是不能保證百分之百執行的。雖然用notifyAll()方法沒有什么簡單的辦法讓指定的線程恢復執行,但在Condition類中確可以很方便的實現此功能,這也是Condition類可以實現多路通知功能的體現。下面我們來演示一下用Condition類怎么實現我們上述的需求。

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
* 用戶登錄
*
* @author Sama
* @author admin@jilinwula.com
* @date 2017-03-15 10:35
* @since 1.0.0
*/
public class Userinfo {

   private Lock lock = new ReentrantLock();
   private Condition condition1 = lock.newCondition();
   private Condition condition2 = lock.newCondition();

   public void await1() {
       try {
           lock.lock();
           System.out.println(String.format("await1線程開始\tthread: %s", Thread.currentThread().getName()));
           condition1.await();
           System.out.println(String.format("await1線程結束\tthread: %s", Thread.currentThread().getName()));
       } catch (InterruptedException e) {
           e.printStackTrace();
       } finally {
           lock.unlock();
       }
   }

   public void await2() {
       try {
           lock.lock();
           System.out.println(String.format("await2線程開始\tthread: %s", Thread.currentThread().getName()));
           condition2.await();
           System.out.println(String.format("await2線程結束\tthread: %s", Thread.currentThread().getName()));
       } catch (InterruptedException e) {
           e.printStackTrace();
       } finally {
           lock.unlock();
       }
   }

   public void signalAll1() {
       lock.lock();
       System.out.println(String.format("恢復所有線程\tthread: %s", Thread.currentThread().getName()));
       condition1.signalAll();
       lock.unlock();
   }

   public void signalAll2() {
       lock.lock();
       System.out.println(String.format("恢復所有線程\tthread: %s", Thread.currentThread().getName()));
       condition2.signalAll();
       lock.unlock();
   }
}
/**
* @author Sama
* @author admin@jilinwula.com
* @date 2017-03-20 13:35
* @since 1.0.0
*/
public class Test {
   public static void main(String[] args) throws InterruptedException {
       Userinfo userinfo = new Userinfo();
       RequestAdmin requestAdmin = new RequestAdmin(userinfo);
       RequestUser requestUser = new RequestUser(userinfo);
       requestAdmin.start();
       requestUser.start();
       Thread.sleep(1000);
       for (int i = 3; i > 0; i--) {
           System.out.println(String.format("倒計時:%s", i));
           Thread.sleep(1000);
       }
       userinfo.signalAll1();
   }
}
await1線程開始	thread: Thread-0
await2線程開始 thread: Thread-1
倒計時:3
倒計時:2
倒計時:1
恢復所有線程 thread: main
await1線程結束 thread: Thread-0

我們看這時就實現了我們上述的需求。用Condition類可以喚醒我們指定的線程,確實比notify()更簡單更方便。

到此,相信大家對“jdk中ReentrantLock類與Condition類結合的使用方法”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

jdk
AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女