Java基础之线程——管理线程同步代码块(BankOperation4)

控制台程序。

除了同步类对象的方法之外,还可以把程序中的语句或代码块制定为synchronized,这种方式更强大,因为可以指定哪个对象从语句或代码块的同步中获益,而不像同步方法那样仅仅是包含代码的对象能获益。这里可以对给定代码块的任何对象设置锁。当对给定对象执行同步的代码块时,就不能执行对相同对象同步的其他代码或方法。

 1 // Defines a customer account
 2 public class Account {
 3   // Constructor
 4   public Account(int accountNumber, int balance) {
 5     this.accountNumber = accountNumber;                                // Set the account number
 6     this.balance = balance;                                            // Set the initial balance
 7   }
 8 
 9   // Return the current balance
10   public int getBalance() {
11     return balance;
12   }
13 
14   // Set the current balance
15   public void setBalance(int balance) {
16     this.balance = balance;
17   }
18 
19   public int getAccountNumber() {
20     return accountNumber;
21   }
22 
23   @Override
24   public String toString() {
25     return "A/C No. " + accountNumber + " : $" + balance;
26   }
27 
28   private int balance;                                                 // The current account balance
29   private int accountNumber;                                           // Identifies this account
30 }
1 // Bank account transaction types
2 public enum TransactionType {DEBIT, CREDIT }
 1 public class Transaction {
 2   // Constructor
 3   public Transaction(Account account, TransactionType type, int amount) {
 4     this.account = account;
 5     this.type = type;
 6     this.amount = amount;
 7   }
 8 
 9   public Account getAccount() {
10     return account;
11   }
12 
13   public TransactionType getTransactionType() {
14     return type;
15   }
16 
17   public int getAmount() {
18     return amount;
19   }
20   @Override
21   public String toString() {
22     return type + " A//C: " + account + ": $" + amount;
23   }
24 
25   private Account account;
26   private int amount;
27   private TransactionType type;
28 }
 1 // Define the bank
 2 
 3 public class Bank {
 4   // Perform a transaction
 5   public void doTransaction(Transaction transaction) {
 6     switch(transaction.getTransactionType()) {
 7       case CREDIT:
 8         synchronized(transaction.getAccount()) {
 9         System.out.println("Start credit of " +
10                 transaction.getAccount() + " amount: " +
11                 transaction.getAmount());
12 
13           // Get current balance
14           int balance = transaction.getAccount().getBalance();
15 
16           // Credits require a lot of checks...
17           try {
18             Thread.sleep(100);
19 
20           } catch(InterruptedException e) {
21             System.out.println(e);
22           }
23           balance += transaction.getAmount();                          // Increment the balance
24           transaction.getAccount().setBalance(balance);                // Restore account balance
25           System.out.println("  End credit of " +
26                   transaction.getAccount() + " amount: " +
27                   transaction.getAmount());
28           break;
29         }
30       case DEBIT:
31         synchronized(transaction.getAccount()) {
32           System.out.println("Start debit of " +
33                   transaction.getAccount() + " amount: " +
34                   transaction.getAmount());
35 
36           // Get current balance
37           int balance = transaction.getAccount().getBalance();
38 
39           // Debits require even more checks...
40           try {
41             Thread.sleep(150);
42 
43           } catch(InterruptedException e) {
44             System.out.println(e);
45           }
46           balance -= transaction.getAmount();                          // Decrement the balance...
47           transaction.getAccount().setBalance(balance);                // Restore account balance
48 
49           System.out.println("  End debit of " +
50                   transaction.getAccount() + " amount: " +
51                   transaction.getAmount());
52           break;
53         }
54 
55       default:                                                         // We should never get here
56         System.out.println("Invalid transaction");
57         System.exit(1);
58     }
59   }
60 }
 1 public class Clerk implements Runnable {
 2   // Constructor
 3   public Clerk(Bank theBank) {
 4     this.theBank = theBank;                                            // Who the clerk works for
 5     inTray = null;                                                     // No transaction initially
 6   }
 7 
 8   // Receive a transaction
 9   public void doTransaction(Transaction transaction) {
10     inTray = transaction;
11   }
12 
13   // The working clerk...
14   public void run() {
15     while(true) {                                                      // Non-stop work...
16       while(inTray == null) {                                          // No transaction waiting?
17         try {
18           Thread.sleep(150);                                           // Then take a break...
19 
20         } catch(InterruptedException e) {
21           System.out.println(e);
22         }
23       }
24 
25       theBank.doTransaction(inTray);
26       inTray = null;                                                   // In-tray is empty
27     }
28   }
29 
30   // Busy check
31   public boolean isBusy() {
32     return inTray != null;                                             // A full in-tray means busy!
33   }
34 
35   private Bank theBank;                                                // The employer - an electronic marvel
36   private Transaction inTray;                                          // The in-tray holding a transaction
37 }
 1 import java.util.Random;
 2 
 3 public class BankOperation4 {
 4   public static void main(String[] args) {
 5     int[] initialBalance = {500, 800};                                 // The initial account balances
 6     int[] totalCredits = new int[initialBalance.length];               // Two different cr totals
 7     int[] totalDebits = new int[initialBalance.length];                // Two different db totals
 8     int transactionCount = 20;                                         // Number of debits and of credits
 9 
10     // Create the account, the bank, and the clerks...
11     Bank theBank = new Bank();                                         // Create a bank
12     Clerk clerk1 = new Clerk(theBank);                                 // Create the first clerk
13     Clerk clerk2 = new Clerk(theBank);                                 // Create the second clerk
14 
15     // Create the accounts, and initialize total credits and debits
16     Account[] accounts = new Account[initialBalance.length];
17     for(int i = 0 ; i < initialBalance.length ; ++i) {
18       accounts[i] = new Account(i+1, initialBalance[i]);               // Create accounts
19       totalCredits[i] = totalDebits[i] = 0;
20     }
21     // Create the threads for the clerks as daemon, and start them off
22     Thread clerk1Thread = new Thread(clerk1);
23     Thread clerk2Thread = new Thread(clerk2);
24     clerk1Thread.setDaemon(true);                                      // Set first as daemon
25     clerk2Thread.setDaemon(true);                                      // Set second as daemon
26     clerk1Thread.start();                                              // Start the first
27     clerk2Thread.start();                                              // Start the second
28 
29     // Create transactions randomly distributed between the accounts
30     Random rand = new Random();
31     Transaction transaction;                                           // Stores a transaction
32     int amount = 0;                                                    // Stores an amount of money
33     int select = 0;                                                    // Selects an account
34     for(int i = 1; i <= transactionCount; i++) {
35       // Choose an account at random for credit operation
36       select = rand.nextInt(accounts.length);
37       amount = 50 + rand.nextInt(26);                                  // Generate amount of $50 to $75
38       transaction = new Transaction(accounts[select],                  // Account
39                               TransactionType.CREDIT,                  // Credit transaction
40                                     amount);                           //  of amount
41       totalCredits[select] += amount;                                  // Keep total credit tally
42 
43       // Wait until the first clerk is free
44       while(clerk1.isBusy()) {
45         try {
46           Thread.sleep(25);                                            // Busy so try later
47         } catch(InterruptedException e) {
48           System.out.println(e);
49         }
50       }
51       clerk1.doTransaction(transaction);                               // Now do the credit
52 
53       // choose an account at random for debit operation
54       select = rand.nextInt(accounts.length);
55       amount = 30 + rand.nextInt(31);                                  // Generate amount of $30 to $60
56       transaction = new Transaction(accounts[select],                  // Account
57                               TransactionType.DEBIT,                   // Debit transaction
58                                     amount);                           //  of amount
59       totalDebits[select] += amount;                                   // Keep total debit tally
60 
61       // Wait until the second clerk is free
62       while(clerk2.isBusy()) {
63         try {
64           Thread.sleep(25);                                            // Busy so try later
65         } catch(InterruptedException e) {
66           System.out.println(e);
67         }
68       }
69       clerk2.doTransaction(transaction);                               // Now do the debit
70     }
71 
72     // Wait until both clerks are done
73     while(clerk1.isBusy() || clerk2.isBusy()) {
74       try {
75         Thread.sleep(25);
76 
77       } catch(InterruptedException e) {
78         System.out.println(e);
79       }
80     }
81 
82     // Now output the results
83     for(int i = 0; i < accounts.length; ++i) {
84       System.out.println("Account Number:"+accounts[i].getAccountNumber()+"
"+
85          "Original balance    : $" + initialBalance[i] + "
" +
86          "Total credits       : $" + totalCredits[i] + "
" +
87          "Total debits        : $" + totalDebits[i] + "
" +
88          "Final balance       : $" + accounts[i].getBalance() + "
" +
89          "Should be           : $" + (initialBalance[i]
90                                    + totalCredits[i]
91                                    - totalDebits[i]) + "
");
92     }
93   }
94 }

synchronized关键字后面圆括号中的表达式用来指定要同步的对象。一旦执行到给定账户对象的同步代码块,就不能再执行为这个账户对象同步的其他代码块或方法。例如,如果用事务的getAccount()方法返回的account[1]对象来引用进行贷款处理的代码块,就不能再执行这个对象的借款处理代码块,但可以执行其他对象的借款处理代码块。

原文地址:https://www.cnblogs.com/mannixiang/p/3446782.html