java5 Condition用法--实现线程间的通信
Condition的功能类似在传统线程技术中的Object.wait()和Object.natify()的功能,传统线程技术实现的互斥只能一个线程单独干,不能说这个线程干完了通知另一个线程来干,Condition就是解决这个问题的,实现线程间的通信。比如CPU让小弟做事,小弟说我先歇着并通知大哥,大哥就开始做事。
Condition 将 Object 监视器方法(wait、notify 和 notifyAll)分解成截然不同的对象,以便通过将这些对象与任意 Lock 实现组合使用,为每个对象提供多个等待 set(wait-set)。其中,Lock 替代了 synchronized 方法和语句的使用,Condition 替代了 Object 监视器方法的使用。
Condition实例实质上被绑定到一个锁上。要为特定 Lock 实例获得 Condition 实例,请使用其 newCondition() 方法。
在java5中,一个锁可以有多个条件,每个条件上可以有多个线程等待,通过调用await()方法,可以让线程在该条件下等待。当调用signalAll()方法,又可以唤醒该条件下的等待的线程。
下面以银行存取款案例阐述Condition用法:
假设有一个账户,多个用户(线程)在同时操作这个账户,有的存款有的取款,存款随便存,取款有限制,不能透支,任何试图透支的操作都将等待里面有足够存款才执行操作。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 | package com.ljq.test.thread; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class ConditionTest { public static void main(String[] args) { ConditionTest test = new ConditionTest(); // 创建并发访问的账户 Account myAccount = test. new Account( "95599200901215522" , 10000 ); // 创建一个线程池 ExecutorService pool = Executors.newFixedThreadPool( 2 ); Thread t1 = test. new DrawThread( "张三" , myAccount, 11000 ); Thread t2 = test. new SaveThread( "李四" , myAccount, 3600 ); Thread t3 = test. new DrawThread( "王五" , myAccount, 2700 ); Thread t4 = test. new SaveThread( "老张" , myAccount, 600 ); Thread t5 = test. new DrawThread( "老牛" , myAccount, 1300 ); Thread t6 = test. new SaveThread( "胖子" , myAccount, 2000 ); // 执行各个线程 pool.execute(t1); pool.execute(t2); pool.execute(t3); pool.execute(t4); pool.execute(t5); pool.execute(t6); // 关闭线程池 pool.shutdown(); } /** * 存款线程类 */ public class SaveThread extends Thread { private String name; // 操作人 private Account account; // 账户 private int x; // 存款金额 SaveThread(String name, Account account, int x) { this .name = name; this .account = account; this .x = x; } public void run() { account.saving(x, name); } } /** * 取款线程类 */ public class DrawThread extends Thread { private String name; // 操作人 private Account account; // 账户 private int x; // 存款金额 DrawThread(String name, Account account, int x) { this .name = name; this .account = account; this .x = x; } public void run() { account.drawing(x, name); } } /** * 银行账户 */ public class Account { private String id; // 账号 private int cash; // 账户余额 private Lock lock = new ReentrantLock(); // 账户锁 private Condition _save = lock.newCondition(); // 存款条件 private Condition _draw = lock.newCondition(); // 取款条件 Account(String id, int cash) { this .id = id; this .cash = cash; } /** * 存款 * * @param x 操作金额 * @param name 操作人 */ public void saving( int x, String name) { lock.lock(); // 获取锁 if (x > 0 ) { cash += x; // 存款 System.out.println(name + "存款" + x + ",当前余额为" + cash); } _draw.signalAll(); // 唤醒所有等待的取款线程。 lock.unlock(); // 释放锁 } /** * 取款 * * @param x * 操作金额 * @param name * 操作人 */ public void drawing( int x, String name) { lock.lock(); // 获取锁 try { if (cash - x < 0 ) { System.out.println(name + "取款失败[余额不足],取款" + x + ",当前余额为" + cash); _draw.await(); // 阻塞取款操作 } else { cash -= x; // 取款 System.out.println(name + "取款" + x + ",当前余额为" + cash); } _save.signalAll(); // 唤醒所有等待的存款操作 } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); // 释放锁 } } } } |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步