package com.panny.thread;public class CreditCard { private String cid; // 信用卡账户 private int balance; // 信用卡余额 public CreditCard(String cid, int balance) { this.cid = cid; this.balance = balance; } public String getCid() { return cid; } public void setCid(String cid) { this.cid = cid; } public int getBalance() { return balance; } public void setBalance(int balance) { this.balance = balance; } public String toString() { return "{" + this.cid + "}"; } }
step_02:定義一個線程安全的操作類SafeOperation.java
package com.panny.thread;import java.util.concurrent.locks.ReadWriteLock;public class SafeOperation implements Runnable { private String atm; // 执行操作的取款机名称 private CreditCard myCard; // 执行操作的信用卡 private int ioCash; // 操作的金额 private ReadWriteLock lock; // 执行操作的对象锁,此处为读写锁 private int operationType; // 操作类型:存款-1, 取款-2, 查询-3 public SafeOperation(String atm, CreditCard myCard, int ioCash, ReadWriteLock lock, int operationType) { this.atm = atm; this.myCard = myCard; this.ioCash = ioCash; this.lock = lock; this.operationType = operationType; } @Override public void run() { // 根据操作类型执行动作 if(this.operationType == 1) { // 存款 makeLock(1); // 打开写入锁(必须) System.out.println("ATM: " + this.atm + "\n" + "CID: " + this.myCard.toString() + "\n" + "TyPE: input" + "\n" + "CURRENT_BALANCE: " + this.myCard.getBalance()+"\n" + "INPUT CASH: " + this.ioCash); try { System.out.println("Doing..."); int currBalance = this.myCard.getBalance(); this.myCard.setBalance(currBalance + this.ioCash); Thread.sleep(2000); System.out.println("SUCCESS!! ATM: " + this.atm + "\n" + "CID: " + this.myCard.toString() + "\n" + "CURRENT_BALANCE: " + this.myCard.getBalance() + "\n"); } catch (InterruptedException e) { e.printStackTrace(); } finally { unlock(1); // 关闭写入锁(必须) } } else if(this.operationType == 2) { makeLock(1); System.out.println("ATM: " + this.atm + "\n" + "CID: " + this.myCard.toString() + "\n" + "TyPE: output" + "\n" + "CURRENT_BALANCE: " + this.myCard.getBalance()+"\n" + "INPUT CASH: " + this.ioCash); try { System.out.println("Doing..."); int currBalance = this.myCard.getBalance(); this.myCard.setBalance(currBalance - this.ioCash); Thread.sleep(2000); System.out.println("SUCCESS!! ATM: " + this.atm + "\n" + "CID: " + this.myCard.toString() + "\n" + "CURRENT_BALANCE: " + this.myCard.getBalance() + "\n"); } catch (InterruptedException e) { e.printStackTrace(); } finally { unlock(1); } } else if(this.operationType == 3) { makeLock(2); try { System.out.println("Doing..."); Thread.sleep(2000); System.out.println("ATM: " + this.atm + "\n" + "CID: " + this.myCard.toString() + "\n" + "TyPE: query" + "\n" + "CURRENT_BALANCE: " + this.myCard.getBalance() + "\n"); } catch (InterruptedException e) { e.printStackTrace(); } finally { unlock(2); } } } /** * 根据参数类型执行打开写入锁(type=1),或打开读取锁(type=2) * @param type */ private void makeLock(int type) { switch(type) { case 1: this.lock.writeLock().lock(); break; case 2: this.lock.readLock().lock(); break; } } /** * 根据参数类型执行关闭写入锁(type=1),或关闭读取锁(type=2) * @param type */ private void unlock(int type) { switch(type) { case 1: this.lock.writeLock().unlock(); break; case 2: this.lock.readLock().unlock(); break; } }}step_03:定義一個測試類 CreditCardTest.java
package com.panny.thread;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.locks.ReentrantReadWriteLock;public class CreditCardTest { public static void main(String[] args) { CreditCard card = new CreditCard("000-111-222", 5000); ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); //--------1 ExecutorService pool = Executors.newCachedThreadPool(); //------------2 SafeOperation operation1 = new SafeOperation("ATM001", card, 200, lock, 1); SafeOperation operation2 = new SafeOperation("ATM002", card, 300, lock, 2); SafeOperation operation3 = new SafeOperation("ATM003", card, 500, lock, 3); SafeOperation operation4 = new SafeOperation("ATM004", card, 100, lock, 1); pool.execute(operation1); pool.execute(operation2); pool.execute(operation3); pool.execute(operation4); pool.shutdown(); //-----------3 }}//---------1:
如果能夠明確區分讀/寫操作,那麼,建議使用讀/寫鎖來提高性能,
否則使用普通鎖:java.util.concurrent.locks.Lock和它的直接子類:ReentrantLock //--------2: java.util.concurrent.Executors: 创建一个线程池,根据需要创建新线程,但当他们是可用的時候,将重用先前构造的线程//--------3: 記得關閉線程池是個好習慣