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

    

posted @ 2015-07-20 00:18  有梦想的小人物  阅读(4264)  评论(3编辑  收藏  举报