JDK1.5 Condition接口

编程技术  /  houtizong 发布于 3年前   80

Condition Object 监视器方法(waitnotify notifyAll)分解成截然不同的对象,以便通过将这些对象与任意 Lock 实现组合使用,为每个对象提供多个等待 set wait-set)。其中,Lock 替代了 synchronized 方法和语句的使用,Condition 替代了 Object 监视器方法的使用。

条件(也称为条件队列或条件变量)为线程提供了一个含义,以便在某个状态条件现在可能为 true 的另一个线程通知它之前,一直挂起该线程(即让其等待)。因为访问此共享状态信息发生在不同的线程中,所以它必须受保护,因此要将某种形式的锁定与该条件相关联。等待提供一个条件的主要属性是:以原子方式释放相关的锁定,并挂起当前线程,就像 Object.wait 做的那样。

Condition 实例实质上被绑定到一个锁定上。要为特定 Lock 实例获得 Condition 实例,请使用其 newCondition() 方法。

作为一个示例,假定有一个绑定的缓冲区,它支持 put take 方法。如果试图在空的缓冲区上执行 take 操作,则在某一个项变得可用之前,线程将一直阻塞;如果试图在满的缓冲区上执行 put 操作,则在有空间变得可用之前,线程将一直阻塞。我们喜欢在单独的等待 set 中保存 put 线程和 take 线程,这样就可以在缓冲区中的项或空间变得可用时利用最佳规划,一次只通知一个线程。可以使用两个 Condition 实例来做到这一点。

 class BoundedBuffer {

   final Lock lock = new ReentrantLock();

   final Condition notFull  = lock.newCondition();

   final Condition notEmpty = lock.newCondition();

 

   final Object[] items = new Object[100];

   int putptr, takeptr, count;

 

   public void put(Object x) throws InterruptedException {

     lock.lock();

     try {

       while (count == items.length)

         notFull.await();

       items[putptr] = x;

       if (++putptr == items.length) putptr = 0;

       ++count;

       notEmpty.signal();

     } finally {

       lock.unlock();

     }

   }

 

   public Object take() throws InterruptedException {

     lock.lock();

     try {

       while (count == 0)

         notEmpty.await();

       Object x = items[takeptr];

       if (++takeptr == items.length) takeptr = 0;

       --count;

       notFull.signal();

       return x;

     } finally {

       lock.unlock();

     }

   }

 }

ArrayBlockingQueue类提供了这项功能,因此没有理由去实现这个示例类。)

Condition 实现可以提供不同于 Object 监视器方法的行为和语义,比如受保证的通知排序,或者在执行通知时不需要保持一个锁定。如果某个实现提供了这样特殊的语义,则该实现必须记录这些语义。

注意,Condition 实例只是一些普通的对象,它们自身可以用作 synchronized 语句中的目标,并且可以调用自己的 wait notification 监视器方法。获取 Condition 实例的监视器锁定或者使用其监视器方法,与获取和该 Condition 相关的 Lock 或使用其 waiting signalling 方法没有什么特定的关系。为了避免混淆,建议除了在其自身的实现中之外,切勿以这种方式使用 Condition 实例。

 

实例:

package com.bijian.thread;public class SaveThread extends Thread {private String name; // 操作人private MyCount myCount; // 账户private int x; // 存款金额public SaveThread(String name, MyCount myCount, int x) {this.name = name;this.myCount = myCount;this.x = x;}public void run() {myCount.saving(x, name);}}

 

package com.bijian.thread;public class DrawThread extends Thread {private String name; // 操作人private MyCount myCount; // 账户private int x; // 存款金额DrawThread(String name, MyCount myCount, int x) {this.name = name;this.myCount = myCount;this.x = x;}public void run() {myCount.drawing(x, name);}}

 

package com.bijian.thread;import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;public class MyCount {private String oid; // 账号private int cash; // 账户余额private Lock lock = new ReentrantLock(); // 账户锁private Condition _save = lock.newCondition(); // 存款条件private Condition _draw = lock.newCondition(); // 取款条件MyCount(String oid, int cash) {this.oid = oid;this.cash = cash;}public void saving(int x, String name) {lock.lock(); // 获取锁try {if (x > 0) {cash += x; // 存款System.out.println(name + "存款" + x + ",当前余额为" + cash);}_draw.signalAll(); // 唤醒所有等待线程。} finally {lock.unlock();}}public void drawing(int x, String name) {lock.lock(); // 获取锁try {if (cash - x < 0) {_draw.await(); // 阻塞取款操作} cash -= x; // 取款System.out.println(name + "取款" + x + ",当前余额为" + cash);_save.signalAll(); // 唤醒所有存款操作} catch (InterruptedException e) {e.printStackTrace();} finally {lock.unlock(); // 释放锁}}}

 

package com.bijian.thread;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class Main {public static void main(String[] args) {//创建并发访问的账户MyCount myCount = new MyCount("95599200901215522", 10000);//创建一个线程池ExecutorService pool = Executors.newFixedThreadPool(2);Thread t1 = new SaveThread("张三", myCount, 2000);Thread t2 = new SaveThread("李四", myCount, 3600);Thread t3 = new DrawThread("王五", myCount, 2700);Thread t4 = new SaveThread("老张", myCount, 600);Thread t5 = new DrawThread("老牛", myCount, 1300);Thread t6 = new DrawThread("胖子", myCount, 800);//执行各个线程pool.execute(t1);pool.execute(t2);pool.execute(t3);pool.execute(t6);pool.execute(t5);pool.execute(t4);//关闭线程池pool.shutdown();}}

 

运行结果:
张三存款2000,当前余额为12000李四存款3600,当前余额为15600王五取款2700,当前余额为12900胖子取款800,当前余额为12100老张存款600,当前余额为12700老牛取款1300,当前余额为11400

 

 

请勿发布不友善或者负能量的内容。与人为善,比聪明更重要!

留言需要登陆哦

技术博客集 - 网站简介:
前后端技术:
后端基于Hyperf2.1框架开发,前端使用Bootstrap可视化布局系统生成

网站主要作用:
1.编程技术分享及讨论交流,内置聊天系统;
2.测试交流框架问题,比如:Hyperf、Laravel、TP、beego;
3.本站数据是基于大数据采集等爬虫技术为基础助力分享知识,如有侵权请发邮件到站长邮箱,站长会尽快处理;
4.站长邮箱:[email protected];

      订阅博客周刊 去订阅

文章归档

文章标签

友情链接

Auther ·HouTiZong
侯体宗的博客
© 2020 zongscan.com
版权所有ICP证 : 粤ICP备20027696号
PHP交流群 也可以扫右边的二维码
侯体宗的博客