• 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
    ",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
    ",account.getBalance());
    33         } catch (InterruptedException e) {
    34             e.printStackTrace();
    35         }
    36     }
    37 }

      结果,相同时间内,存与取执行后应该是相等的。如果我们在方法中不去使用synchronized关键字,那么得出的结果就不对了。

      

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

        

  • 相关阅读:
    2015.05.12:json的常用处理方式
    好菜都得花功夫做
    网站从 IIS6 迁移至 IIS7 后的通配符脚本映射权限配置不当可能导致403错误
    ELearning是学习系统而不是教育系统
    空难与软件开发(一)
    “模态”对话框和“后退”按钮
    闭包解析(Fun with closure)
    关于CultureInfo的两个问题
    从来就不可能精通:关于Boxing
    Windows RT 应用程序开发介绍培训的讲义
  • 原文地址:https://www.cnblogs.com/LIANQQ/p/4660252.html
Copyright © 2020-2023  润新知