Java线程-线程池-条件变量

条件变量是Java5线程当中很重要的一个概念,顾名思义,条件变量就是条件当中的一种变量,这里的条件没有实际意义,仅仅是个标记而已。
条件变量都实现了java.util.concurrent.locks.Condition接口,条件对象的实例化是通过一个lock对象上调用newCondition()方法来获取的,这样条件就和一个锁对象绑定起来,Java当中的条件变量只能和锁配合使用,来控制并发程序访问竞争资源的安全。
条件变量的出现是为了更精细的控制线程的等待和唤醒,Java5之前,线程的等待与唤醒靠的是Object对象的wait()、notify和notifyAll()方法,这样的处理不够精细。
在Java5当中,一个锁可以有多个条件,每个条件上可以有多个线程等待,通过调用await()方法,可以使线程在该条件下进行等待。当调用了signalAll(),又可以唤醒该条件下等待的线程。
条件变量比较抽象,它不是自然语言当中的条件概念,它是控制程序的一种有效手段。
代码如下:

public class Main {
    public static void main(String args[]){
        //创建并发访问的账户
        MyCount myCount=new MyCount("370911199212233321",10000);
        //创建一个线程池
        ExecutorService executorService= Executors.newFixedThreadPool(2);
        //创建六个线程
        Thread thread1=new SaveMoneyThread("张三",myCount,1000);
        Thread thread2=new DrawMoneyThread("王五",myCount,5000);
        Thread thread3=new SaveMoneyThread("赵六",myCount,2000);
        Thread thread4=new SaveMoneyThread("李四",myCount,1000);
        Thread thread5=new DrawMoneyThread("吴京",myCount,8000);
        Thread thread6=new SaveMoneyThread("狗子",myCount,7000);
        Thread thread7=new DrawMoneyThread("王二麻子",myCount,9000);
        //执行各个线程
        executorService.execute(thread1);
        executorService.execute(thread2);
        executorService.execute(thread3);
        executorService.execute(thread4);
        executorService.execute(thread5);
        executorService.execute(thread6);
        executorService.execute(thread7);
        //关闭线程池
        executorService.shutdown();
    }

}

class MyCount {
    private String oid;                                 //账号
    private int cash;                                   //账户余额
    private Lock lock=new ReentrantLock();              //锁
    private Condition saveCondition=lock.newCondition();//存款条件
    private Condition drawCondition=lock.newCondition();//取款条件

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

    /**
     *  存款
     * @param x 存款金额
     * @param name 存款人
     */
    public void saveMoney(int x,String name){
        lock.lock();
        if(x>0){
            this.cash+=x;//存款
            System.out.println(name+"存款"+x+","+"当前余额为"+this.cash);
        }
        //唤醒取款的等待线程
        this.drawCondition.signalAll();
        //释放锁
        lock.unlock();
    }

    /**
     * 取款
     * @param x 取款金额
     * @param name 取款人
     */
    public void drawMoney(int x,String name){
        try {
            lock.lock();
            if(x-this.cash>0){
                drawCondition.await();
            }else {
                this.cash-=x;
                System.out.println(name+"取款"+x+",当前余额为"+this.cash);
            }
            //唤醒所有的存款条件
            saveCondition.signalAll();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            //释放锁
            lock.unlock();
        }
    }
}

class DrawMoneyThread extends Thread {

    private String name;    //操作人
    private MyCount myCount;//账户
    private int x;          //取款金额

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

    /**
     * 取款
     */
    @Override
    public void run() {
        this.myCount.drawMoney(this.x,this.name);
    }
}

class SaveMoneyThread extends Thread {
    private String name;    //操作人
    private MyCount myCount;//账户
    private int x;          //存款金额

    SaveMoneyThread(String name,MyCount myCount,int x){
        this.name=name;
        this.myCount=myCount;
        this.x=x;
    }
    /**
     * 存款
     */
    @Override
    public void run() {
        this.myCount.saveMoney(this.x,this.name);
    }
}

如果不用Condition来实现,用synchronized来实现,代码如下:

public class Main {
    public static void main(String args[]){
        //创建并发访问的账户
        MyCount myCount=new MyCount("370911199212233321",10000);
        //创建一个线程池
        ExecutorService executorService= Executors.newFixedThreadPool(2);
        //创建六个线程
        Thread thread1=new SaveMoneyThread("张三",myCount,1000);
        Thread thread2=new DrawMoneyThread("王五",myCount,5000);
        Thread thread3=new SaveMoneyThread("赵六",myCount,2000);
        Thread thread4=new SaveMoneyThread("李四",myCount,1000);
        Thread thread5=new DrawMoneyThread("吴京",myCount,8000);
        Thread thread6=new SaveMoneyThread("狗子",myCount,7000);
        Thread thread7=new DrawMoneyThread("王二麻子",myCount,9000);
        //执行各个线程
        executorService.execute(thread1);
        executorService.execute(thread2);
        executorService.execute(thread3);
        executorService.execute(thread4);
        executorService.execute(thread5);
        executorService.execute(thread6);
        executorService.execute(thread7);
        //关闭线程池
        executorService.shutdown();
    }

}

class MyCount {
    private String oid;                                 //账号
    private int cash;                                   //账户余额
    MyCount(String oid,int cash){
        this.oid=oid;
        this.cash=cash;
    }

    /**
     *  存款
     * @param x 存款金额
     * @param name 存款人
     */
    public synchronized void saveMoney(int x,String name){
        if(x>0){
            this.cash+=x;//存款
            System.out.println(name+"存款"+x+","+"当前余额为"+this.cash);
        }
        //唤醒取款的等待线程
        notifyAll();
    }

    /**
     * 取款
     * @param x 取款金额
     * @param name 取款人
     */
    public synchronized void drawMoney(int x,String name){
        try {
            if(x-this.cash>0){
                wait();
            }else {
                this.cash-=x;
                System.out.println(name+"取款"+x+",当前余额为"+this.cash);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        notifyAll();
    }
}

class DrawMoneyThread extends Thread {

    private String name;    //操作人
    private MyCount myCount;//账户
    private int x;          //取款金额

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

    /**
     * 取款
     */
    @Override
    public void run() {
        this.myCount.drawMoney(this.x,this.name);
    }
}

class SaveMoneyThread extends Thread {
    private String name;    //操作人
    private MyCount myCount;//账户
    private int x;          //存款金额

    SaveMoneyThread(String name,MyCount myCount,int x){
        this.name=name;
        this.myCount=myCount;
        this.x=x;
    }
    /**
     * 存款
     */
    @Override
    public void run() {
        this.myCount.saveMoney(this.x,this.name);
    }
}

用同步代码块来实现:

public class Main {
    public static void main(String args[]){
        //创建并发访问的账户
        MyCount myCount=new MyCount("370911199212233321",10000);
        //创建一个线程池
        ExecutorService executorService= Executors.newFixedThreadPool(2);
        //创建六个线程
        Thread thread1=new SaveMoneyThread("张三",myCount,1000);
        Thread thread2=new DrawMoneyThread("王五",myCount,5000);
        Thread thread3=new SaveMoneyThread("赵六",myCount,2000);
        Thread thread4=new SaveMoneyThread("李四",myCount,1000);
        Thread thread5=new DrawMoneyThread("吴京",myCount,8000);
        Thread thread6=new SaveMoneyThread("狗子",myCount,7000);
        Thread thread7=new DrawMoneyThread("王二麻子",myCount,9000);
        //执行各个线程
        executorService.execute(thread1);
        executorService.execute(thread2);
        executorService.execute(thread3);
        executorService.execute(thread4);
        executorService.execute(thread5);
        executorService.execute(thread6);
        executorService.execute(thread7);
        //关闭线程池
        executorService.shutdown();
    }

}

class MyCount {
    private String oid;                                 //账号
    private int cash;                                   //账户余额
    MyCount(String oid,int cash){
        this.oid=oid;
        this.cash=cash;
    }

    /**
     *  存款
     * @param x 存款金额
     * @param name 存款人
     */
    public void saveMoney(int x,String name){
        if(x>0){
            synchronized (this){

                this.cash+=x;//存款
                System.out.println(name+"存款"+x+","+"当前余额为"+this.cash);
                //唤醒取款的等待线程
                notifyAll();

            }
        }
    }

    /**
     * 取款
     * @param x 取款金额
     * @param name 取款人
     */
    public void drawMoney(int x,String name){
        synchronized (this){
            try {
                if(x-this.cash>0){
                    wait();
                }else {
                    this.cash-=x;
                    System.out.println(name+"取款"+x+",当前余额为"+this.cash);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            notifyAll();
        }
    }
}

class DrawMoneyThread extends Thread {

    private String name;    //操作人
    private MyCount myCount;//账户
    private int x;          //取款金额

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

    /**
     * 取款
     */
    @Override
    public void run() {
        this.myCount.drawMoney(this.x,this.name);
    }
}

class SaveMoneyThread extends Thread {
    private String name;    //操作人
    private MyCount myCount;//账户
    private int x;          //存款金额

    SaveMoneyThread(String name,MyCount myCount,int x){
        this.name=name;
        this.myCount=myCount;
        this.x=x;
    }
    /**
     * 存款
     */
    @Override
    public void run() {
        this.myCount.saveMoney(this.x,this.name);
    }
}

你可能感兴趣的:(Java,线程)