转载

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; 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.000000Account : Final Balance: 1000.000000

正文到此结束
Loading...