Java並發編程實戰(使用synchronized實現同步方法)


    本文介紹java最基本的同步方式,即使用synchronized關鍵字來控制一個方法的並發訪問,如果一個對象已用synchronized關鍵字聲明,那么只有一個執行線程允許去訪問它,其它試圖訪問這個對象的線程將被掛起,直到第一個線程訪問完畢。

   下面通過一個小例子來學習這個概念,公司向銀行存錢,取錢場景。

  1:創建Account的賬號類,它是銀行賬戶的模型,只有一個雙精度浮點型屬性,balance.

  2:實現balance的get set 方法。

  3:實現AddAmount()方法,將傳入的數量加到余額balance中,並且在同一時間只允許一個線程去改變這個值,使用synchronized關鍵字。

  4:實現SubtractAmount()方法,將傳入的數量從余額balance中扣除,並且在同一時間只允許一個線程去改變這個值。

  具體代碼:

    

 1 public class Account {
 2 
 3     /**
 4      * Balance of the bank account
 5      */
 6     private double balance;
 7 
 8     /**
 9      * Returns the balance of the account
10      * @return the balance of the account
11      */
12     public double getBalance() {
13         return balance;
14     }
15 
16     /**
17      * Establish the balance of the account
18      * @param balance the new balance of the account
19      */
20     public void setBalance(double balance) {
21         this.balance = balance;
22     }
23     
24     /**
25      * Add an import to the balance of the account
26      * @param amount import to add to the balance
27      */
28     public synchronized void addAmount(double amount) {
29             double tmp=balance;
30             try {
31                 Thread.sleep(10);
32             } catch (InterruptedException e) {
33                 e.printStackTrace();
34             }
35             tmp+=amount;
         balance=tmp;
36 } 37 38 /** 39 * Subtract an import to the balance of the account 40 * @param amount import to subtract to the balance 41 */ 42 public synchronized void subtractAmount(double amount) { 43 double tmp=balance; 44 try { 45 Thread.sleep(10); 46 } catch (InterruptedException e) { 47 e.printStackTrace(); 48 } 49 tmp-=amount; 50 balance=tmp; 51 } 52 53 }

 

  5:實現一個ATM模擬類Bank,它使用subtractAmount()方法對賬戶的余額進行扣除,實現Runabl接口。

   具體代碼:

    

 1 public class Bank implements Runnable {
 2 
 3     /**
 4      * The account affected by the operations
 5      */
 6     private Account account;
 7     
 8     /**
 9      * Constructor of the class. Initializes the account
10      * @param account The account affected by the operations
11      */
12     public Bank(Account account) {
13         this.account=account;
14     }
15     
16     
17     /**
18      * Core method of the Runnable
19      */
20     public void run() {
21         for (int i=0; i<100; i++){
22             account.subtractAmount(1000);
23         }
24     }
25 
26 }

  6:實現公司模擬類,調用addAmount()方法進行存錢,實現Runabl接口。

  具體代碼:

  

 1 public class Company implements Runnable {
 2 
 3     /**
 4      * The account affected by the operations
 5      */
 6     private Account account;
 7     
 8     /**
 9      * Constructor of the class. Initializes the account
10      * @param account the account affected by the operations
11      */
12     public Company(Account account) {
13         this.account=account;
14     }
15     
16     /**
17      * Core method of the Runnable
18      */
19     public void run() {
20         for (int i=0; i<100; i++){
21             account.addAmount(1000);
22         }
23     }

  7:在主方法中調用測試:通過線程的join方法,在存期那,取錢線程模擬完畢后打印出結構。

  

 1 public class Main {
 2 
 3     /**
 4      * Main method of the example
 5      * @param args
 6      */
 7     public static void main(String[] args) {
 8         // Creates a new account ...
 9         Account    account=new Account();
10         // an initialize its balance to 1000
11         account.setBalance(1000);
12         
13         // Creates a new Company and a Thread to run its task
14         Company    company=new Company(account);
15         Thread companyThread=new Thread(company);
16         // Creates a new Bank and a Thread to run its task
17         Bank bank=new Bank(account);
18         Thread bankThread=new Thread(bank);
19         
20         // Prints the initial balance
21         System.out.printf("Account : Initial Balance: %f\n",account.getBalance());
22         
23         // Starts the Threads
24         companyThread.start();
25         bankThread.start();
26 
27         try {
28             // Wait for the finalization of the Threads
29             companyThread.join();
30             bankThread.join();
31             // Print the final balance
32             System.out.printf("Account : Final Balance: %f\n",account.getBalance());
33         } catch (InterruptedException e) {
34             e.printStackTrace();
35         }
36     }
37 }

  結果,相同時間內,存與取執行后應該是相等的。如果我們在方法中不去使用synchronized關鍵字,那么得出的結果就不對了。

  

  Account : Initial Balance: 1000.000000
  Account : Final Balance: 1000.000000

    


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM