在Object的wait,notify,notifyAll上做了一层封装,时锁的控制更细化。条件变量的出现是为了更精细的控制线程等待与唤醒,一个锁可以有多个条件,每个条件上有多个线程等待,通过await()方法,可以让线程在该条件下等待。当调用signalAll()方法时,又可以唤醒该条件下等待的线程

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;

/**
 * Java线程:条件变量
 *
 * @author leizhimin 2009-11-5 10:57:29
 */
public class Test1 {
    public static void main(String[] args) {
        //创建并发访问的账户
        MyCount myCount = new MyCount("95599200901215522", 10000);
        //创建一个线程池
        ExecutorService pool = Executors.newFixedThreadPool(6);
        Thread t1 = new SaveThread("张三", myCount, 1);
        Thread t2 = new SaveThread("李四", myCount, 2);
        Thread t3 = new SaveThread("王五", myCount, 3);
        Thread t4 = new DrawThread("老张", myCount, 4);
        Thread t5 = new DrawThread("老牛", myCount, 5);
        Thread t6 = new DrawThread("胖子", myCount, 6);
        //执行各个线程
        pool.execute(t1);
        pool.execute(t2);
        pool.execute(t3);
        pool.execute(t4);
        pool.execute(t5);
        pool.execute(t6);
        //关闭线程池
        pool.shutdown();
    }
}

/**
 * 存款线程类
 */
class SaveThread extends Thread {
    private String name;                //操作人
    private MyCount myCount;        //账户
    private int x;                            //存款金额

    SaveThread(String name, MyCount myCount, int x) {
        this.name = name;
        this.myCount = myCount;
        this.x = x;
    }

    public void run() {
        myCount.saving(x, name);
    }
}

/**
 * 取款线程类
 */
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);
    }
}


/**
 * 普通银行账户,不可透支
 */
class MyCount {
    private String oid;                         //账号
    private int cash;                             //账户余额
    private Lock lock = new ReentrantLock();                //账户锁
    public Condition _save = lock.newCondition();    //存款条件
    public Condition _draw = lock.newCondition();    //取款条件

    MyCount(String oid, int cash) {
        this.oid = oid;
        this.cash = cash;
    }

    public static void sleep() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     * 存款
     *
     * @param x    操作金额
     * @param name 操作人
     */
    public void saving(int x, String name) {
        try {
            lock.lock();                        //获取锁

            _save.await();                     // 等待存钱通知
            _draw.signal();                    // 存钱后通知取钱

            cash += x;                    //存款
            sleep();
            System.out.println(name + "存款" + x + ",当前余额为" + cash);

            lock.unlock();                    //释放锁
        } catch (InterruptedException e) {
        }
    }

    /**
     * 取款
     *
     * @param x    操作金额
     * @param name 操作人
     */
    public void drawing(int x, String name) {
        try {
            lock.lock();                                 //获取锁
            if (x == 6) {
                _save.signal();                         // 当取钱是6时,触发存钱
            } else {
                _draw.await();                          // 取钱不是6时,等待
                _save.signal();                         // 去前后触发存钱
            }
            cash -= x;                     //取款
            sleep();
            System.out.println(name + "取款" + x + ",当前余额为" + cash);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();                     //释放锁
        }
    }
}