温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

jdk中ReentrantLock类与Condition类结合的使用方法

发布时间:2021-07-13 09:07:04 来源:亿速云 阅读:103 作者: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