java线程并发包util.concurrent的研究(七)

使用ReentrantLock的实例

 

一、实例简介:

       本例子是典型的多线程竞争的范例:两个银行职员同时操作同一账号。本人分别使用不加任何控制、使用ReentrantLock、使用synchronized的三种方式实现,并比较其结果。

 

二、类列表:

类名

功能

Account

银行账号类

Bank

银行类:定义调用操作账号的事务方法

BankWithSync

银行类:使用synchronized定义调用操作账号的事务方法

Transaction

账号事务类:定义入账/出账等对银行账号的操作

Clerk

银行职员类:使用Bank类作为构造方法的参数,实现了Runnable接口,按照事务类型对银行账号进行入账/出账操作(不使用锁)

ClerkWithSync

银行职员类:使用BankWithSync类作为构造方法的参数,实现了Runnable接口,按照事务类型对银行账号进行入账/出账操作

ClerkWithLock

银行职员类:使用Bank类作为构造方法的参数,实现了Runnable接口,按照事务类型对银行账号进行入账/出账操作(使用ReentrantLock

multiClerkConcurrentTransaction

提供调用简介中的三种方式实现两个银行职员同时操作同一账号。

operationWithUnuseLock-未使用锁进行账号的事务操作

operationWithReentrantLock-使用可重入锁进行账号的事务操作

operationWithSynchronized-使用synchronized进行账号的事务操作

其中operationWithUnuseLock主要使用了: Clerk类和Bank类;

operationWithReentrantLock主要使用了: ClerkWithLock类和Bank类。

operationWithSynchronized主要使用了: ClerkWithSync类和BankWithSync类。

运行结果:
初始存款:$500
入账金额:$856
出账金额:$888
最终存款:$-22
应为        :$468
未使用锁花费6480ms

初始存款:$500
入账金额:$841
出账金额:$878
最终存款:$463
应为        :$463
使用Reentrant锁花费6639ms

初始存款:$500
入账金额:$832
出账金额:$873
最终存款:$459
应为        :$459
使用synchornized同步花费6249ms

三、源代码:

/*

 * Account.java

 *

 * Created on 2005125, 下午3:15

 */

 

package bjInfoTech.util.threadManage.concurrent.tryIt.bank;

 

/**

 * 定义银行账户类

 * @author 聪明的猪

 */

public class Account {

    private int balance;

    private int accountNumber;

   

    /**

     * 银行账户构造方法

     * @param accountNumber 用户帐号

     * @param balance 帐号余额

     */

    public Account(int accountNumber,int balance) {

        this.accountNumber=accountNumber;

        this.balance=balance;

    }

   

    /**

     * 返回帐号余额

     * @return 帐号余额

     */

    public int getBalance(){

        return balance;

    }

   

    /**

     * 赋值帐号余额

     * @param balance 余额

     */

    public void setBalance(int balance){

        this.balance=balance;

    }

   

    /**

     * 返回银行帐号

     * @return 银行帐号

     */

    public int getAccountNumber(){

        return accountNumber;

    }

   

    public String toString(){

        return "No."+accountNumber+" :$"+balance;

    }

 

   

}

 

/*

 * Bank.java

 *

 * Created on 2005125, 下午3:54

 */

 

package bjInfoTech.util.threadManage.concurrent.tryIt.bank;

import bjInfoTech.util.threadManage.concurrent.tryIt.bank.*;

 

/**

 * 银行类,主要执行事务

 * @author 聪明的猪

 */

public class Bank {

   

    /** Creates a new instance of Bank */

    public Bank() {

    }

   

    /**

     * 执行事务,按照事务的类型对用户帐号的余额进行操作。

     * @param transaction transaction对象

     */

    public void doTransaction(Transaction transaction){

        int balance=transaction.getAccount().getBalance();

       

        switch(transaction.getTransactionType()){

            case Transaction.CREDIT:

                try{

                    Thread.sleep(100);

                }

                catch(InterruptedException e){

                    System.out.println(e);

                }

                balance+=transaction.getAmount();

                break;

            case Transaction.DEBIT:

                try{

                    Thread.sleep(150);

                }

                catch(InterruptedException e){

                    System.out.println(e);

                }

                balance-=transaction.getAmount();

                break;

            default:

                System.out.println("无效的事务");

                System.exit(1);

        }

        transaction.getAccount().setBalance(balance);

    }

}

 

/*

 * BankWithSync.java

 *

 * Created on 2005125, 下午3:54

 */

 

package bjInfoTech.util.threadManage.concurrent.tryIt.bank;

import bjInfoTech.util.threadManage.concurrent.tryIt.bank.*;

 

/**

 * 银行类,主要执行事务(使用synchronized同步)

 * @author 聪明的猪

 */

public class BankWithSync {

   

    /** Creates a new instance of Bank */

    public BankWithSync() {

    }

   

    /**

     * 执行事务,按照事务的类型对用户帐号的余额进行操作(使用synchronized同步)

     * @param transaction transaction对象

     */

    synchronized public void doTransaction(Transaction transaction){

        int balance=transaction.getAccount().getBalance();

       

        switch(transaction.getTransactionType()){

            case Transaction.CREDIT:

                try{

                    Thread.sleep(100);

                }

                catch(InterruptedException e){

                    System.out.println(e);

                }

                balance+=transaction.getAmount();

                break;

            case Transaction.DEBIT:

                try{

                    Thread.sleep(150);

                }

                catch(InterruptedException e){

                    System.out.println(e);

                }

                balance-=transaction.getAmount();

                break;

            default:

                System.out.println("无效的事务");

                System.exit(1);

        }

        transaction.getAccount().setBalance(balance);

    }

}

 

/*

 * Clerk.java

 *

 * Created on 2005125, 下午4:01

 */

 

package bjInfoTech.util.threadManage.concurrent.tryIt.bank;

import bjInfoTech.util.threadManage.concurrent.tryIt.bank.*;

 

/**

 * 定义银行职员类(没使用锁)

 * @author 聪明的猪

 */

public class Clerk implements Runnable{

    private Bank theBank;

    private Transaction inTray;

   

    /**

     * 构造银行职员类

     * @param theBank 银行类对象

     */

    public Clerk(Bank theBank) {

        this.theBank=theBank;

        inTray=null;

    }

   

    /**

     * 银行职员执行事务

     * @param transaction 事务类对象

     */

    public void doTransaction(Transaction transaction){

        inTray=transaction;

    }

   

    /**

     * 线程的run方法

     */

    public void run(){

        while(true){

            while(inTray==null){

                try{

                    Thread.sleep(150);

                }

                catch(InterruptedException e){

                    System.out.println(e);

                }

            }

             theBank.doTransaction(inTray);

            inTray=null;

        }

      

    }

   

    /**

     * 返回职员是否忙碌

     * @return 如果职员忙碌,则返回true;否则返回false

     */

    public boolean isBusy(){

        return inTray!=null;

    }

}

 

/*

 * ClerkWithLock.java

 *

 * Created on 2005125, 下午4:01

 */

 

package bjInfoTech.util.threadManage.concurrent.tryIt.bank;

import bjInfoTech.util.threadManage.concurrent.tryIt.bank.*;

import edu.emory.mathcs.backport.java.util.concurrent.locks.*;

import edu.emory.mathcs.backport.java.util.concurrent.*;

 

/**

 * 定义银行职员类(使用ReenTrantLock)

 * @author 聪明的猪

 */

public class ClerkWithLock implements Runnable{

    private Bank theBank;

    private Transaction inTray;

    private ReentrantLock lock;

    /**

     * 构造银行职员类

     * @param theBank 银行类对象

     * @param lock 可重入的锁对象

     */

    public ClerkWithLock(Bank theBank,ReentrantLock lock) {

        this.theBank=theBank;

        this.lock=lock;

        inTray=null;

    }

   

    /**

     * 银行职员执行事务(使用ReentrantLock同步)

     * @param transaction 事务类对象

     */

    public void doTransaction(Transaction transaction){

        inTray=transaction;

    }

  

/**

     * 线程的run方法

     */

    public void run(){

        while(true){

            while(inTray==null){

                try{

                    Thread.sleep(150);

                }

                catch(InterruptedException e){

                    System.out.println(e);

                }

            }

            try{

                lock.lockInterruptibly();

                theBank.doTransaction(inTray);

                inTray=null;

                lock.unlock();

            }

            catch(InterruptedException e){

                if (lock.isHeldByCurrentThread()){

                    lock.unlock();

                }

                System.out.println(e);

            }

        }

      

    }

   

    /**

     * 返回职员是否忙碌

     * @return 如果职员忙碌,则返回true;否则返回false

     */

    public boolean isBusy(){

        return inTray!=null;

    }

}

 

/*

 * ClerkWithSync.java

 *

 * Created on 2005125, 下午4:01

 */

 

package bjInfoTech.util.threadManage.concurrent.tryIt.bank;

import bjInfoTech.util.threadManage.concurrent.tryIt.bank.*;

 

/**

 * 定义银行职员类(Bank的事务方法使用synchronized同步)

 * @author 聪明的猪

 */

public class ClerkWithSync implements Runnable{

    private BankWithSync theBank;

    private Transaction inTray;

   

    /**

     * 构造银行职员类(Bank的事务方法使用synchronized同步)

     * @param theBank 银行类对象

     */

    public ClerkWithSync(BankWithSync theBank) {

        this.theBank=theBank;

        inTray=null;

    }

   

    /**

     * 银行职员执行事务

     * @param transaction 事务类对象

     */

    public void doTransaction(Transaction transaction){

        inTray=transaction;

    }

   

    /**

     * 线程的run方法

     */

    public void run(){

        while(true){

            while(inTray==null){

                try{

                    Thread.sleep(150);

                }

                catch(InterruptedException e){

                    System.out.println(e);

                }

            }

             theBank.doTransaction(inTray);

            inTray=null;

        }

      

    }

   

    /**

     * 返回职员是否忙碌

     * @return 如果职员忙碌,则返回true;否则返回false

     */

    public boolean isBusy(){

        return inTray!=null;

    }

}

 

/*

 * Transaction.java

 *

 * Created on 2005125, 下午3:13

 */

 

package bjInfoTech.util.threadManage.concurrent.tryIt.bank;

 

/**

 * 银行事务类

 * @author 聪明的猪

 */

public class Transaction {

        public static final int DEBIT=0;

        public static final int CREDIT=1;

        public static String[] types={"Debit","Credit"};

        private Account account;

        private int amount;

        private int transactionType;

             

        /**

         * 事务类的构造方法

         * @param account 银行账户

         * @param transactionType 事务类型(入账/出账)

         * @param amount 入账/出账金额

         */

        public Transaction(Account account,int transactionType,int amount){

            this.account=account;

            this.transactionType=transactionType;

            this.amount=amount;

        }

       

        /**

         * 返回用户帐号类

         * @return 用户帐号类

         */

        public Account getAccount(){

            return account;

        }

       

        /**

         * 返回事务类型

         * @return 事务类型字符串

         */

        public int getTransactionType(){

            return transactionType;

        }

       

        /**

         * 返回操作金额

         * @return 操作金额

         */

        public int getAmount(){

            return amount;

        }

       

        public String toString(){

            return types[transactionType]+": "+":$"+amount;

        }

   

}

 

/*

 * multiClerkConcurrentTransaction.java

 *

 * Created on 2005125, 下午4:10

 */

 

package bjInfoTech.util.threadManage.concurrent.tryIt.bank;

import bjInfoTech.util.threadManage.concurrent.tryIt.bank.*;

import edu.emory.mathcs.backport.java.util.concurrent.locks.*;

import java.util.Random;

 

/**

 * 多个银行职员并发访问同一银行账号

 * @author 聪明的猪

 */

public class multiClerkConcurrentTransaction {

   

    /** Creates a new instance of multiClerkConcurrentTransaction */

    public multiClerkConcurrentTransaction() {

    }

   

    /**

     * 未使用锁进行账号的事务操作

     */

    public static void operationWithUnuseLock(){

        int initialBalance=500;

        int totalCredits=0;

        int totalDebits=0;

        int transactionCount=20;

       

        Bank theBank=new Bank();

        Clerk clerk1=new Clerk(theBank);

        Clerk clerk2=new Clerk(theBank);

        Account account=new Account(1,initialBalance);

       

        Thread clerk1Thread=new Thread(clerk1);

        Thread clerk2Thread=new Thread(clerk2);

        clerk1Thread.setDaemon(true);

        clerk2Thread.setDaemon(true);

        clerk1Thread.start();

        clerk2Thread.start();

       

        Random rand=new Random();

        Transaction transaction;

       

        int amount=0;

       

        //职员1和职员2共进行20次事务操作

        for(int i=1;i<=transactionCount;i++){

            //职员1入账amount

            transaction=new Transaction(account,Transaction.CREDIT,amount);

            totalCredits+=amount;

       

            while(clerk1.isBusy()){

                try{

                    Thread.sleep(25);

                }

                catch(InterruptedException e){

                    System.out.println(e);

                }

            }

            clerk1.doTransaction(transaction);

          

            //职员2出账amount

            amount=30+rand.nextInt(31);

            transaction=new Transaction(account,Transaction.DEBIT,amount);

            totalDebits+=amount;

           

            while(clerk2.isBusy()){

                try{

                    Thread.sleep(25);

                }

                catch(InterruptedException e){

                    System.out.println(e);

                }

            }

            clerk2.doTransaction(transaction);

        }

       

        //等待两职员工作结束

        while(clerk1.isBusy()||clerk2.isBusy()){

                try{

                    Thread.sleep(25);

                }

                catch(InterruptedException e){

                    System.out.println(e);

                }

        }

       

        //打印结果

        System.out.println(

                "初始存款:$"+initialBalance+"/n"+

                "入账金额:$"+totalCredits+"/n"+

                "出账金额:$"+totalDebits+"/n"+

                "最终存款:$"+account.getBalance()+"/n"+

                "应为        :$"+(initialBalance+totalCredits-totalDebits));

    }

   

/**

     * 使用可重入锁进行账号的事务操作

     */

    public static void operationWithReentrantLock(){

        int initialBalance=500;

        int totalCredits=0;

        int totalDebits=0;

        int transactionCount=20;

        ReentrantLock lock=new ReentrantLock();

        Bank theBank=new Bank();

        ClerkWithLock clerk1=new ClerkWithLock(theBank,lock);

        ClerkWithLock clerk2=new ClerkWithLock(theBank,lock);

        Account account=new Account(1,initialBalance);

       

        Thread clerk1Thread=new Thread(clerk1);

        Thread clerk2Thread=new Thread(clerk2);

        clerk1Thread.setDaemon(true);

        clerk2Thread.setDaemon(true);

        clerk1Thread.start();

        clerk2Thread.start();

       

        Random rand=new Random();

        Transaction transaction;

       

        int amount=0;

       

        //职员1和职员2共进行20次事务操作

        for(int i=1;i<=transactionCount;i++){

            //职员1入账amount

            transaction=new Transaction(account,Transaction.CREDIT,amount);

            totalCredits+=amount;

       

            while(clerk1.isBusy()){

                try{

                    Thread.sleep(25);

                }

                catch(InterruptedException e){

                    System.out.println(e);

                }

            }

            clerk1.doTransaction(transaction);

          

            //职员2出账amount

            amount=30+rand.nextInt(31);

            transaction=new Transaction(account,Transaction.DEBIT,amount);

            totalDebits+=amount;

           

            while(clerk2.isBusy()){

                try{

                    Thread.sleep(25);

                }

                catch(InterruptedException e){

                    System.out.println(e);

                }

            }

            clerk2.doTransaction(transaction);

        }

       

        //等待两职员工作结束

        while(clerk1.isBusy()||clerk2.isBusy()){

                try{

                    Thread.sleep(25);

                }

                catch(InterruptedException e){

                    System.out.println(e);

                }

        }

       

        //打印结果

        System.out.println(

                "初始存款:$"+initialBalance+"/n"+

                "入账金额:$"+totalCredits+"/n"+

                "出账金额:$"+totalDebits+"/n"+

                "最终存款:$"+account.getBalance()+"/n"+

                "应为        :$"+(initialBalance+totalCredits-totalDebits));

    }

   

    /**

     * 使用synchronized进行账号的事务操作

     */

    public static void operationWithSynchronized(){

        int initialBalance=500;

        int totalCredits=0;

        int totalDebits=0;

        int transactionCount=20;

       

        BankWithSync theBank=new BankWithSync();

        ClerkWithSync clerk1=new ClerkWithSync(theBank);

        ClerkWithSync clerk2=new ClerkWithSync(theBank);

        Account account=new Account(1,initialBalance);

       

        Thread clerk1Thread=new Thread(clerk1);

        Thread clerk2Thread=new Thread(clerk2);

        clerk1Thread.setDaemon(true);

        clerk2Thread.setDaemon(true);

        clerk1Thread.start();

        clerk2Thread.start();

       

        Random rand=new Random();

        Transaction transaction;

       

        int amount=0;

       

        //职员1和职员2共进行20次事务操作

        for(int i=1;i<=transactionCount;i++){

            //职员1入账amount

            transaction=new Transaction(account,Transaction.CREDIT,amount);

            totalCredits+=amount;

       

            while(clerk1.isBusy()){

                try{

                    Thread.sleep(25);

                }

                catch(InterruptedException e){

                    System.out.println(e);

                }

            }

            clerk1.doTransaction(transaction);

          

            //职员2出账amount

            amount=30+rand.nextInt(31);

            transaction=new Transaction(account,Transaction.DEBIT,amount);

            totalDebits+=amount;

           

            while(clerk2.isBusy()){

                try{

                    Thread.sleep(25);

                }

                catch(InterruptedException e){

                    System.out.println(e);

                }

            }

            clerk2.doTransaction(transaction);

        }

       

        //等待两职员工作结束

        while(clerk1.isBusy()||clerk2.isBusy()){

                try{

                    Thread.sleep(25);

                }

                catch(InterruptedException e){

                    System.out.println(e);

                }

        }

       

        //打印结果

        System.out.println(

                "初始存款:$"+initialBalance+"/n"+

                "入账金额:$"+totalCredits+"/n"+

                "出账金额:$"+totalDebits+"/n"+

                "最终存款:$"+account.getBalance()+"/n"+

                "应为        :$"+(initialBalance+totalCredits-totalDebits));

    }

   

    public static void main(String[] argv){

        operationWithUnuseLock();

        operationWithReentrantLock();

        operationWithSynchronized();

    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值