Java基础之线程——管理线程同步方法(BankOperation2)

控制台程序。

当两个或多个线程共享同一资源时,例如文件或内存块,就需要采取措施,确保其中的一个线程不会修改另一个线程正在使用的资源。当其中的一个线程更新文件中的某个记录,同时另一个线程正在检索这个记录,就会出现灾难性的结果。管理这种情形的一种方式是对涉及的线程使用同步机制。

同步的目标是当多个线程希望访问同一资源时,确保在任意时刻只有一个线程可以访问。使用同步机制可以通过两种方式管理线程的执行:

1、可以在方法级别管理代码,这涉及方法的同步。

2、可以在块级别管理代码,这使用块的同步。

同步方法可以使任意类中方法的子集(或者所有的方法)都是互斥的,在任意时刻都只能执行其中的一个方法。使用synchronized关键字声明类中的方法,就可以把它们设置为互斥的。

 1 // Define the bank
 2 
 3 public class Bank {
 4   // Perform a transaction
 5   synchronized public void doTransaction(Transaction transaction) {
 6     int balance = transaction.getAccount().getBalance();               // Get current balance
 7 
 8     switch(transaction.getTransactionType()) {
 9       case CREDIT:
10         // Credits require a lot of checks...
11         try {
12           Thread.sleep(100);
13 
14         } catch(InterruptedException e) {
15           System.out.println(e);
16         }
17         balance += transaction.getAmount();                            // Increment the balance
18         break;
19 
20       case DEBIT:
21         // Debits require even more checks...
22         try {
23           Thread.sleep(150);
24 
25         } catch(InterruptedException e) {
26           System.out.println(e);
27         }
28         balance -= transaction.getAmount();                            // Decrement the balance
29         break;
30 
31       default:                                                         // We should never get here
32         System.out.println("Invalid transaction");
33         System.exit(1);
34    }
35     transaction.getAccount().setBalance(balance);                      // Restore the account balance
36   }
37 }
 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 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 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 import java.util.Random;
 2 
 3 public class BankOperation2 {
 4   public static void main(String[] args) {
 5     int initialBalance = 500;                                          // The initial account balance
 6     int totalCredits = 0;                                              // Total credits on the account
 7     int totalDebits =0;                                                // Total debits on the account
 8     int transactionCount = 20;                                         // Number of debits and 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     Account account = new Account(1, initialBalance);                  // Create an account
15 
16     // Create the threads for the clerks as daemon, and start them off
17     Thread clerk1Thread = new Thread(clerk1);
18     Thread clerk2Thread = new Thread(clerk2);
19     clerk1Thread.setDaemon(true);                                      // Set first as daemon
20     clerk2Thread.setDaemon(true);                                      // Set second as daemon
21     clerk1Thread.start();                                              // Start the first
22     clerk2Thread.start();                                              // Start the second
23 
24     // Generate transactions of each type and pass to the clerks
25     Random rand = new Random();                                        // Random number generator
26     Transaction transaction;                                           // Stores a transaction
27     int amount = 0;                                                    // stores an amount of money
28     for(int i = 1 ; i <= transactionCount ; ++i) {
29       amount = 50 + rand.nextInt(26);                                  // Generate amount of $50 to $75
30       transaction = new Transaction(account,                           // Account
31                               TransactionType.CREDIT,                  // Credit transaction
32                                     amount);                           //  of amount
33       totalCredits += amount;                                          // Keep total credit tally
34 
35       // Wait until the first clerk is free
36       while(clerk1.isBusy()) {
37         try {
38           Thread.sleep(25);                                            // Busy so try later
39 
40         } catch(InterruptedException e) {
41           System.out.println(e);
42         }
43       }
44       clerk1.doTransaction(transaction);                               // Now do the credit
45 
46       amount = 30 + rand.nextInt(31);                                  // Generate amount of $30 to $60
47       transaction = new Transaction(account,                           // Account
48                                TransactionType.DEBIT,                  // Debit transaction
49                                     amount);                           //  of amount
50       totalDebits += amount;                                           // Keep total debit tally
51       // Wait until the second clerk is free
52       while(clerk2.isBusy()) {
53         try {
54           Thread.sleep(25);                                            // Busy so try later
55 
56         } catch(InterruptedException e) {
57           System.out.println(e);
58         }
59       }
60       clerk2.doTransaction(transaction);                               // Now do the debit
61     }
62 
63     // Wait until both clerks are done
64     while(clerk1.isBusy() || clerk2.isBusy()) {
65       try {
66         Thread.sleep(25);
67 
68       } catch(InterruptedException e) {
69         System.out.println(e);
70       }
71     }
72 
73     // Now output the results
74     System.out.println(
75               "Original balance : $" + initialBalance+"
" +
76               "Total credits    : $" + totalCredits+"
" +
77               "Total debits     : $" + totalDebits+"
" +
78               "Final balance    : $" + account.getBalance() + "
" +
79               "Should be        : $" + (initialBalance + totalCredits - totalDebits));
80   }
81 }


把处理账户的方法声明为synchronized,在其中一个职员对账户调用方法时,禁止另一个职员也调用同一个方法。

目前存在的问题是:银行的效率非常低,当其中一个职员在处理事物时,另一个职员却在闲着。

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