歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

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

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

還有一篇:Java並發編程:synchronized  http://www.linuxidc.com/Linux/2015-07/120169.htm

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

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

  2:實現balance的get set 方法。

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

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

  具體代碼:

public class Account {

    /**
    * Balance of the bank account
    */
    private double balance;

    /**
    * Returns the balance of the account
    * @return the balance of the account
    */
    public double getBalance() {
        return balance;
    }

    /**
    * Establish the balance of the account
    * @param balance the new balance of the account
    */
    public void setBalance(double balance) {
        this.balance = balance;
    }
   
    /**
    * Add an import to the balance of the account
    * @param amount import to add to the balance
    */
    public synchronized void addAmount(double amount) {
            double tmp=balance;
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            tmp+=amount;
    }
   
    /**
    * Subtract an import to the balance of the account
    * @param amount import to subtract to the balance
    */
    public synchronized void subtractAmount(double amount) {
            double tmp=balance;
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            tmp-=amount;
            balance=tmp;
    }
   
}

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

具體代碼:

public class Bank implements Runnable {

    /**
    * The account affected by the operations
    */
    private Account account;
   
    /**
    * Constructor of the class. Initializes the account
    * @param account The account affected by the operations
    */
    public Bank(Account account) {
        this.account=account;
    }
   
   
    /**
    * Core method of the Runnable
    */
    public void run() {
        for (int i=0; i<100; i++){
            account.subtractAmount(1000);
        }
    }

}

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

  具體代碼:

public class Company implements Runnable {

    /**
    * The account affected by the operations
    */
    private Account account;
   
    /**
    * Constructor of the class. Initializes the account
    * @param account the account affected by the operations
    */
    public Company(Account account) {
        this.account=account;
    }
   
    /**
    * Core method of the Runnable
    */
    public void run() {
        for (int i=0; i<100; i++){
            account.addAmount(1000);
        }
    }

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

public class Main {

    /**
    * Main method of the example
    * @param args
    */
    public static void main(String[] args) {
        // Creates a new account ...
        Account    account=new Account();
        // an initialize its balance to 1000
        account.setBalance(1000);
       
        // Creates a new Company and a Thread to run its task
        Company    company=new Company(account);
        Thread companyThread=new Thread(company);
        // Creates a new Bank and a Thread to run its task
        Bank bank=new Bank(account);
        Thread bankThread=new Thread(bank);
       
        // Prints the initial balance
        System.out.printf("Account : Initial Balance: %f\n",account.getBalance());
       
        // Starts the Threads
        companyThread.start();
        bankThread.start();

        try {
            // Wait for the finalization of the Threads
            companyThread.join();
            bankThread.join();
            // Print the final balance
            System.out.printf("Account : Final Balance: %f\n",account.getBalance());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

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

Copyright © Linux教程網 All Rights Reserved