線程同步的必要性

一、帳戶類java

package com.ljb.app.synchronize;
/**
 * 模擬帳戶類(線程同步必要性)
 * @author LJB
 * @version 2015年3月10日
 */
public class Account {
 // 餘額
 private int balance = 500;
 
 // 查詢餘額
 public int getBalance() {
  return balance;
 }
 // 取款(這裏沒有設置餘額判斷<餘額大於0,餘額足夠支付取款數量>)
 public void withdraw (int amount) {
  balance = balance - amount;
 }
}

二、取款線程(擁有同一個帳戶)app

 package com.ljb.app.synchronize;
/**
 * 取款線程(模擬動態取款)
 * @author LJB
 * @version 2015年3月10日
 */
public class WithdrawThread implements Runnable{
 /*
  *  全部用此對象建立的線程共享同一個帳戶
  */
 private Account account = new Account();
 
 /*
  *  取款、查詢餘額(non-Javadoc)
  * @see java.lang.Runnable#run()
  */
 public void run () {
  for (int i = 0 ; i < 5 ; i++) {
   // 取款
   makeWithdraw(100);
   
   // 查詢餘額
   if (account.getBalance() < 0) {
    System.out.println("帳戶透支了!");
   }
  } 
 }
 
 /*
  * 取款 (餘額不足給出提示)
  */
 private void makeWithdraw (int amount) {
  if (account.getBalance() >= amount) {
   System.out.println(Thread.currentThread().getName() + "準備取款。");
   
   try {
    Thread.sleep(500);
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
   
   // 0.5秒以後完成取款
   account.withdraw(amount);
   System.out.println(Thread.currentThread().getName() + "完成取款。");
  } else {
   System.out.println("餘額不足以支付" 
        + Thread.currentThread().getName()
        + "的取款,餘額爲" + account.getBalance());
  }
 }
}

三、測試類測試

 package com.ljb.app.synchronize;
/**
 * 建立2個線程同時使用同一個帳戶
 * @author LJB
 * @version 2015年3月10日
 */
public class TestWithdraw {
 /**
  * @param args
  */
 public static void main(String[] args) {
  // 建立實現Runnable接口類實例
  WithdrawThread withdraw = new WithdrawThread();
  
  // 建立2個線程
  Thread husband = new Thread(withdraw);
  Thread wife = new Thread(withdraw);
  
  husband.setName("丈夫");
  wife.setName("妻子");
  
  husband.start();
  wife.start();
 }
}

運行結果:spa

丈夫準備取款。
妻子準備取款。
妻子完成取款。
妻子準備取款。
丈夫完成取款。
丈夫準備取款。
妻子完成取款。
妻子準備取款。
丈夫完成取款。
丈夫準備取款。
妻子完成取款。
丈夫完成取款。
妻子準備取款。
丈夫準備取款。
丈夫完成取款。
帳戶透支了!
妻子完成取款。
帳戶透支了!
餘額不足以支付妻子的取款,餘額爲-100
帳戶透支了!
餘額不足以支付丈夫的取款,餘額爲-100
帳戶透支了!
四、同步方法
線程

/*
  * 取款 (餘額不足給出提示)
  */
 private synchronized void makeWithdraw (int amount) {
  if (account.getBalance() >= amount) {
   System.out.println(Thread.currentThread().getName() + "準備取款。");
   
   try {
    Thread.sleep(500);
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
   
   // 0.5秒以後完成取款
   account.withdraw(amount);
   System.out.println(Thread.currentThread().getName() + "完成取款。");
  } else {
   System.out.println("餘額不足以支付" 
        + Thread.currentThread().getName()
        + "的取款,餘額爲" + account.getBalance());
  }
 }

運行結果:code

丈夫準備取款。
丈夫完成取款。
妻子準備取款。
妻子完成取款。
妻子準備取款。
妻子完成取款。
妻子準備取款。
妻子完成取款。
丈夫準備取款。
丈夫完成取款。
餘額不足以支付丈夫的取款,餘額爲0
餘額不足以支付丈夫的取款,餘額爲0
餘額不足以支付丈夫的取款,餘額爲0
餘額不足以支付妻子的取款,餘額爲0
餘額不足以支付妻子的取款,餘額爲0
對象

 五、同步代碼塊(比同步方法更強大)接口

/*
  * 取款 (餘額不足給出提示)
  */
 private void makeWithdraw (int amount) {
  synchronized (account) {
   if (account.getBalance() >= amount) {
    System.out.println(Thread.currentThread().getName() + "準備取款。");
    
    try {
     Thread.sleep(500);
    } catch (InterruptedException e) {
     e.printStackTrace();
    }
    
    // 0.5秒以後完成取款
    account.withdraw(amount);
    System.out.println(Thread.currentThread().getName() + "完成取款。");
   } else {
    System.out.println("餘額不足以支付" 
         + Thread.currentThread().getName()
         + "的取款,餘額爲" + account.getBalance());
   }
  }
 }
相關文章
相關標籤/搜索