面試題:請寫出線程同步相關的方法,以銀行帳號存儲款爲例

一.該面試題主要考察多線程中的synchronized或者Lock的使用

 * 線程同步 :使用同步方法,實現線程同步
 * 同步synchronized方法的對象監視鎖爲this,當前對象
 * 多個線程使用同一把鎖,若是線程安全必需確保:多個線程使用的是同一個this對象(Runnable適用於共享同一對象[如:this],若是Thread繼承就會有問題[推薦使用Runnable])
 * 全部訪問此對象方法的線程都在方法外等待,都會判斷同步鎖,下降效率,但確保線程安全問題
 * java的每一個對象都有一個內置鎖,當用synchronized關鍵字修飾方法時,內置鎖會保護整個方法。在調用該方法前,線程須要得到內置鎖,不然就處於阻塞狀
java

synchronized關鍵字也能夠修飾靜態方法,此時若是調用該靜態方法,將會鎖住整個類面試

此例子中使用synchronized關鍵字:安全

private synchronized void makeWithdraw(int amount){...}多線程

二.上代碼

BankAccount.java併發

 1 public class BankAccount {
 2     //餘額
 3     private int balance = 500;
 4     //查詢
 5     public int getBalance(){
 6         return balance;
 7     }
 8     //取款
 9     public void withdraw(int amount){
10         balance = balance - amount;
11     }
12     //存款
13     public void deposit(int amount){
14         balance = balance + amount;
15     }
16 }

 SyncMethod.javaide

 1 /**
 2  * 此線程類實現Runnable接口
 3  * 線程同步 :使用同步方法,實現線程同步
 4  * 同步synchronized方法的的對象監視鎖爲this,當前對象
 5  * 多個線程使用同一把鎖,若是線程安全必需確保:多個線程使用的是同一個this對象
 6  * 全部訪問此對象方法的線程都在方法外等待,都會判斷同步鎖,下降效率,但確保線程安全問題
 7  * */
 8 public class SyncMethod implements Runnable {
 9     // 全部Thread多線程線程都共享Runnable(接口對象)和account對象
10     private BankAccount account = new BankAccount();
11     @Override
12     public void run() {
13         for (int i = 0; i < 5; i++) {// 總共取款5次
14             makeWithdraw(100); // 每次取款100
15             if (account.getBalance() < 0) {
16                 System.out.println("☆" + Thread.currentThread().getName()+ "   透支了!");
17             }
18         }
19     }
20 
21     /**
22      * makeWithdraw 帳戶取款
23      * @param amount取款金額
24      * 打印log記錄取款過程
25      * */
26     private synchronized void makeWithdraw(int amount){
27         if(account.getBalance() >= amount){//若是餘額足夠則取款
28             System.out.println("☆" + Thread.currentThread().getName() + "   準備取款!");
29             try {
30                 Thread.sleep(500);
31             } catch (InterruptedException e) {
32                 System.out.println(Thread.currentThread().getName() + "   準備取款,等待0.5s線程中斷!" + e.getMessage());
33             }
34             account.withdraw(amount);
35             System.out.println("☆" + Thread.currentThread().getName() + "   完成" + amount + "取款!餘額爲" + account.getBalance());
36         }else{//餘額不足則提示
37             System.out.println("☆" + "餘額不足以支付" + Thread.currentThread().getName() + amount + "   的取款,餘額爲" + account.getBalance());
38         }
39     }
40 }

TreadSyncTest.java單元測試

 1 public class TreadSyncTest {
 2 
 3     /*
 4         Junit不適合多線程併發測試。
 5         由於線程還在激活狀態的時候,Junit已經執行完成。
 6         在Junit的TestRunner中,它沒有被設計成搜尋Runnable實例,
 7         而且等待這些線程發出報告,它只是執行它們而且忽略了它們的存在。
 8         綜上,不可能在Junit中編寫和維護多線程的單元測試。
 9      */    
10     /*
11         @Test
12         public void test() {
13         }
14     */
15     
16     public static void main(String[] args) {
17         //實現Runnable:全部Thread多線程線程都共享Runnable(接口對象)
18         //NoSync target =new NoSync();
19         SyncMethod target = new SyncMethod();
20         //建立羅密歐和朱麗葉兩個線程實現取款(同時)
21         Thread romeoThread = new Thread(target);
22         romeoThread.setName("羅密歐");
23         Thread julietThread = new Thread(target);
24         julietThread.setName("朱麗葉");
25         //調用Thread對象的start()方法,啓動線程,執行run()方法(OS)
26         romeoThread.start();
27         julietThread.start();
28     }
29 }

 運行結果:測試

正常運行結果1:
☆羅密歐   準備取款!
☆羅密歐   完成100取款!餘額爲400
☆羅密歐   準備取款!
☆羅密歐   完成100取款!餘額爲300
☆羅密歐   準備取款!
☆羅密歐   完成100取款!餘額爲200
☆羅密歐   準備取款!
☆羅密歐   完成100取款!餘額爲100
☆羅密歐   準備取款!
☆羅密歐   完成100取款!餘額爲0
☆餘額不足以支付朱麗葉100   的取款,餘額爲0
☆餘額不足以支付朱麗葉100   的取款,餘額爲0
☆餘額不足以支付朱麗葉100   的取款,餘額爲0
☆餘額不足以支付朱麗葉100   的取款,餘額爲0
☆餘額不足以支付朱麗葉100   的取款,餘額爲0.

正常運行結果2:
☆羅密歐   準備取款!
☆羅密歐   完成100取款!餘額爲400
☆羅密歐   準備取款!
☆羅密歐   完成100取款!餘額爲300
☆羅密歐   準備取款!
☆羅密歐   完成100取款!餘額爲200
☆羅密歐   準備取款!
☆羅密歐   完成100取款!餘額爲100
☆朱麗葉   準備取款!
☆朱麗葉   完成100取款!餘額爲0
☆餘額不足以支付朱麗葉100   的取款,餘額爲0
☆餘額不足以支付朱麗葉100   的取款,餘額爲0
☆餘額不足以支付朱麗葉100   的取款,餘額爲0
☆餘額不足以支付羅密歐100   的取款,餘額爲0
☆餘額不足以支付朱麗葉100   的取款,餘額爲0

正常運行結果3:
☆羅密歐   準備取款!
☆羅密歐   完成100取款!餘額爲400
☆羅密歐   準備取款!
☆羅密歐   完成100取款!餘額爲300
☆羅密歐   準備取款!
☆羅密歐   完成100取款!餘額爲200
☆朱麗葉   準備取款!
☆朱麗葉   完成100取款!餘額爲100
☆朱麗葉   準備取款!
☆朱麗葉   完成100取款!餘額爲0
☆餘額不足以支付朱麗葉100   的取款,餘額爲0
☆餘額不足以支付朱麗葉100   的取款,餘額爲0
☆餘額不足以支付朱麗葉100   的取款,餘額爲0
☆餘額不足以支付羅密歐100   的取款,餘額爲0
☆餘額不足以支付羅密歐100   的取款,餘額爲0

若是不用synchronized關鍵字的結果:this

☆羅密歐   準備取款!
☆朱麗葉   準備取款!
☆朱麗葉   完成100取款!餘額爲300
☆羅密歐   完成100取款!餘額爲300
☆羅密歐   準備取款!
☆朱麗葉   準備取款!
☆朱麗葉   完成100取款!餘額爲100
☆朱麗葉   準備取款!
☆羅密歐   完成100取款!餘額爲100
☆羅密歐   準備取款!
☆羅密歐   完成100取款!餘額爲0
☆餘額不足以支付羅密歐100   的取款,餘額爲0
☆餘額不足以支付羅密歐100   的取款,餘額爲0
☆朱麗葉   完成100取款!餘額爲-100
☆朱麗葉   透支了!
☆餘額不足以支付朱麗葉100   的取款,餘額爲-100
☆朱麗葉   透支了!
☆餘額不足以支付朱麗葉100   的取款,餘額爲-100
☆朱麗葉   透支了!

 

此博文轉載並整理於:http://blog.csdn.net/typa01_kk/article/details/46738459spa

相關文章
相關標籤/搜索