Condition 将 Object 监视器方法(wait、notify和 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
相关推荐
包含 jdk1.5免安装、jdk1.6免安装、jdk1.8(32和64)
jdk1.5.exe jdk1.5 jdk1.5下载
前几天上传过这个资源,因为是在jdk1.6上开发的, 测试了一下在jdk1.5上不能用, 今天重新用jdk1.5编译了一下, 这个是可以支持jdk1.5+的 将 pu-xlscommon-1.0.0.jar 添加到工程的 /lib 目录下 用法在附件中 XlsTest....
JDK1.5,JDK1.5
绝版jdk1.5,非常不错的资源。用起来很好。是 Java语言对Bean类属性、事件的一种缺省处理方法。例如类A中有属性name,那我们可以通过getName,setName来得到其值或者设置新 的值。通过getName/setName来访问name属性,...
测试可用的linux版jdk1.5,jdk-1_5_0_19-linux-i586-rpm.bin
jdk1.5.0.22 是jdk1.5的最后一版,jdk1.5 windows 64位官方正式版,绝对有效,jdk1.5 windows 64位官方正式版,绝对有效
jdk 1.5 中文 api chm jdk 1.5 中文 api chm
jdk1.5.0.22 是jdk1.5的最后一版
很实用的JAVA API中文参考文档,如果你开始讨厌HTML版本的API中文文档,试试这个吧,强大的索引功能使你开发更加愉快,分两卷,要都下了才能解压。
JDK1.5 API完整版JDK1.5 API完整版JDK1.5 API完整版
Java-jdk1.5安装包
“JDK1.5”(开发代号猛虎)的一个重要主题就是通过新增一些特性来简化开发,这些特性包括泛型,for-else 循环,自动装包/拆包,枚举,可变参数, 静态导入
详细介绍java对象的使用和说明详细介绍java对象的使用和说明详细介绍java对象的使用和说明详细介绍java对象的使用和说明详细介绍java对象的使用和说明
Jdk1.5Doc_CN.chm Jdk1.5Doc_CN.chm Jdk1.5Doc_CN.chm Jdk1.5Doc_CN.chm
jdk1.5压缩包 解压缩可用 用于Windows系统
jdk1.5 64位 windows版
JDK1.5+1.6整合版(文件为txt文件,里面有百度网盘下载地址<文件太大所以用网盘>) 文件里含有1.5和1.6两个版本的JDK,并且附有一环境变量创建办法以及切换版本方法
转载 jdk1.5的一些新特性,希望能帮助大家!
jdk1.5api,方便搜索版,不解释,谁用谁知道