JDK1.5 Condition接口
编程技术  /  houtizong 发布于 3年前   80
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
请勿发布不友善或者负能量的内容。与人为善,比聪明更重要!
技术博客集 - 网站简介:
前后端技术:
后端基于Hyperf2.1框架开发,前端使用Bootstrap可视化布局系统生成
网站主要作用:
1.编程技术分享及讨论交流,内置聊天系统;
2.测试交流框架问题,比如:Hyperf、Laravel、TP、beego;
3.本站数据是基于大数据采集等爬虫技术为基础助力分享知识,如有侵权请发邮件到站长邮箱,站长会尽快处理;
4.站长邮箱:[email protected];
文章归档
文章标签
友情链接