Java并发编程实例--13.方法同步(synchronized)

使用synchronized关键字去控制对某个方法的并发调用。

某一时段内,只能有一个线程可以读取该方法。

其他线程需要等待前面线程调用完毕后方可调用。



不过,静态方法有着不同的行为。

虽然也是每次只能有一个线程调用它,但是另一个线程可以调用该类对象的其他非静态方法。

这一点需要注意,因为如果2个线程可读取2个不同的同步方法,一个是静态另一个不是。

如果这2个方法修改的是同样的数据,可能会导致数据不一致错误。



本例中,我们将有一个银行账户和2个线程;1个线程存钱,1个线程取钱。这种情况,如果不适用方法同步机制账户里的钱就不对了。方法同步机制保证了账户的最终平衡。



Account.java
package com.dylan.thread.ch2.c01.task;

/**
 * This class simulates a bank account 
 *
 */
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 the import to add to the balance of the account
	 */
	public synchronized void addAmount(double amount) {
		double tmp=balance;
		try {
			Thread.sleep(10);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		tmp+=amount;
		balance=tmp;
	}
	
	/**
	 * Subtract an import to the balance of the account
	 * @param amount the import to subtract to the balance of the account 
	 */
	public synchronized void subtractAmount(double amount) {
		double tmp=balance;
		try {
			Thread.sleep(10);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		tmp-=amount;
		balance=tmp;
	}
	
}

Company.java
package com.dylan.thread.ch2.c01.task;

/**
 * This class simulates a company that pays a salary an
 * insert money into an account 
 *
 */
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);
		}
	}

}


Bank.java

package com.dylan.thread.ch2.c01.task;

/**
 * This class simulates a bank or a cash dispenser that takes money
 * from an account
 * 
 */
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);
		}
	}

}

Main.java

package com.dylan.thread.ch2.c01.core;

import com.dylan.thread.ch2.c01.task.Account;
import com.dylan.thread.ch2.c01.task.Bank;
import com.dylan.thread.ch2.c01.task.Company;

/**
 * Main class of the example. It creates an account, a company and a bank
 * to work with the account. The final balance is equal to the initial.
 *
 */
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();
		}
	}
}


运行结果:

Account : Initial Balance: 1000.000000
deposit 1000, balance:2000.0
deposit 1000, balance:3000.0
withdraw 1000, balance:2000.0
withdraw 1000, balance:1000.0
withdraw 1000, balance:0.0
deposit 1000, balance:1000.0
withdraw 1000, balance:0.0
deposit 1000, balance:1000.0
withdraw 1000, balance:0.0
deposit 1000, balance:1000.0
withdraw 1000, balance:0.0
deposit 1000, balance:1000.0
withdraw 1000, balance:0.0
deposit 1000, balance:1000.0
withdraw 1000, balance:0.0
deposit 1000, balance:1000.0
withdraw 1000, balance:0.0
deposit 1000, balance:1000.0
withdraw 1000, balance:0.0
deposit 1000, balance:1000.0
Account : Final Balance: 1000.000000



猜你喜欢

转载自blog.csdn.net/indexman/article/details/80216725
今日推荐