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.000000
Account : Final Balance: 1000.000000
转载自:http://www.cnblogs.com/LIANQQ/p/4660252.html


浙公网安备 33010602011771号