有一个账户,多个用户(线程)在同时操作这个账户,有的存款有的取款,存款随便存,取款有限制,不能透支,任何试图透支的操作都将等待里面有足够存款才执行操作。
如果程序不使用synchronized关键字来保证同步,而直接用lock.那么系统中不存在隐式的同步监视器,就不能使用wait,notify,notifyAll方法进行线程通信了.但使用Lock对象来保证同步时,Java提供了一个Condition类来保持协调,使用Condition可以让那些已经得到Lock对象但无法继续执行的线程释放Lock对象,Condition对象也可以唤醒其他等待的线程.这情况下,Lock替代了同步方法或同步代码块,Condition替代了同步监视器的功能.
Condition实例绑定在Lock对象上,要获得需要调用Lock对象的newCondition方法.有3个方法:
- await():类似于隐式同步监视器上的wait方法.该await方法有更多的重载方法.
- signal():任意唤醒一个Lock对象上等待的单个线程.只有当前线程放弃对该Lock对象的锁定后(使用await()方法),才可以自行被唤醒的线程.
- signalAll():唤醒所有等待线程。
package com.thread.lock;import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;public class MyCount { private String id; // 账号 private int cash; // 账户余额 private Lock lock = new ReentrantLock(); // 账户锁 private Condition _save = lock.newCondition(); // 存款条件 private Condition _draw = lock.newCondition(); // 取款条件 MyCount(String id, int cash) { this.id = id; this.cash = cash; } /** * 存款 * * @param name * 存款人姓名 * @param cash * 存款金额 */ public void saving(String name, int saveCash) { lock.lock(); if (saveCash > 0) { cash += saveCash; System.out.println(name + " 存款 " + saveCash + ",当前余额为" + cash); } _draw.signalAll(); // 唤醒所有等待线程。 lock.unlock(); // 释放锁 } /** * 取款 * * @param name * 取款人姓名 * @param cash * 取款金额 */ public void drawing(String name, int saveCash) { lock.lock(); try { if (cash < saveCash) { _draw.await(); // 阻塞取款操作 } else { cash -= saveCash;// 取款 System.out.println(name + " 取款 " + saveCash + ",当前余额为" + cash); } _save.signalAll(); // 唤醒所有存款操作 } catch (InterruptedException e) { System.out.println(name + " 取款超额了" + " 取款金额为:" + saveCash); // TODO Auto-generated catch block // e.printStackTrace(); } finally { lock.unlock(); } }}class DrawThread extends Thread { private String name; // 操作人 private MyCount myCount; // 账户 private int saveCash; // 存款金额 DrawThread(String name, MyCount myCount, int saveCash) { this.name = name; this.myCount = myCount; this.saveCash = saveCash; } @Override public void run() { myCount.drawing(name, saveCash); }}class SaveThread extends Thread { private String name; // 操作人 private MyCount myCount; // 账户 private int saveCash; // 存款金额 SaveThread(String name, MyCount myCount, int saveCash) { this.name = name; this.myCount = myCount; this.saveCash = saveCash; } @Override public void run() { myCount.saving(name, saveCash); }}package com.thread.lock;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class TestLock { public void run(){ ExecutorService pool = Executors.newFixedThreadPool(5); MyCount count = new MyCount("43089183736746383", 1200); SaveThread save1 = new SaveThread("张三",count, 200); SaveThread save2 = new SaveThread("李四",count, 100); DrawThread draw1 = new DrawThread("王五", count, 1600); DrawThread draw2 = new DrawThread("赵六", count, 500); SaveThread save3 = new SaveThread("王杰",count, 3000); pool.execute(save1); pool.execute(save2); pool.execute(draw1); pool.execute(draw2); pool.execute(save3); pool.shutdownNow(); } public static void main(String[] args) { new TestLock().run(); }}