Java基础之线程——使用执行器(UsingExecutors)

控制台程序。

在这个版本的银行示例中,把借款和贷款事务创建为在不同线程中执行的任务,它们把事务提交给职员。创建事务的任务是Callable<>任务,因为它们需要返回已为每个账户创建的借款或贷款事务的总额。

 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: " + ": $" + 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     synchronized(transaction.getAccount()) {
 7       int balance = 0;
 8       switch(transaction.getTransactionType()) {
 9         case CREDIT:
10           System.out.println("Start credit of " +
11                   transaction.getAccount() + " amount: " +
12                   transaction.getAmount());
13 
14             // Get current balance
15             balance = transaction.getAccount().getBalance();
16 
17             // Credits require a lot of checks...
18             try {
19               Thread.sleep(100);
20 
21             } catch(InterruptedException e) {
22               System.out.println(e);
23             }
24             balance += transaction.getAmount();                        // Increment the balance
25             transaction.getAccount().setBalance(balance);              // Restore account balance
26             System.out.println("  End credit of " +
27                     transaction.getAccount() + " amount: " +
28                     transaction.getAmount());
29             break;
30         case DEBIT:
31             System.out.println("Start debit of " +
32                     transaction.getAccount() + " amount: " +
33                     transaction.getAmount());
34 
35             // Get current balance
36             balance = transaction.getAccount().getBalance();
37 
38             // Debits require even more checks...
39             try {
40               Thread.sleep(150);
41 
42             } catch(InterruptedException e) {
43               System.out.println(e);
44             }
45             balance -= transaction.getAmount();                        // Decrement the balance...
46             transaction.getAccount().setBalance(balance);              // Restore account balance
47 
48             System.out.println("  End debit of " +
49                     transaction.getAccount() + " amount: " +
50                     transaction.getAmount());
51             break;
52 
53         default:                                                       // We should never get here
54           System.out.println("Invalid transaction");
55           System.exit(1);
56       }
57     }
58   }
59 }
 1 import java.util.List;
 2 import java.util.Collections;
 3 import java.util.LinkedList;
 4 
 5 public class Clerk implements Runnable {
 6   // Constructor
 7   public Clerk(int ID, Bank theBank) {
 8     this.ID = ID;
 9     this.theBank = theBank;                                            // Who the clerk works for
10   }
11 
12   // Receive a transaction
13   synchronized public boolean doTransaction(Transaction transaction) {
14     if(inTray.size() >= maxTransactions)
15       return false;
16     inTray.add(transaction);                                           // Add transaction to the list
17     return true;
18   }
19 
20   // The working clerk...
21    public void run() {
22     while(true) {
23       while(inTray.size() == 0) {                                      // No transaction waiting?
24         try {
25           Thread.sleep(200);                                           // then take a break
26           if(inTray.size() != 0) {
27             break;
28           } else {
29             return;
30           }
31         } catch(InterruptedException e) {
32           System.out.println("Clerk "+ ID + "
" + e);
33           return;
34         }
35       }
36       theBank.doTransaction(inTray.remove(0));
37       if(Thread.interrupted()) {
38         System.out.println("Interrupt flag for Clerk " + ID + " set. Terminating.");
39         return;
40       }
41     }
42   }
43 
44   int ID;
45   private Bank theBank;
46   private List<Transaction> inTray =                                   // The in-tray holding transactions
47                    Collections.synchronizedList(new LinkedList<Transaction>());
48   private int maxTransactions = 8;                                     // Maximum transactions in the in-tray
49 }
 1 // Generates transactions for clerks
 2 import java.util.Random;
 3 import java.util.Vector;
 4 import java.util.concurrent.Callable;
 5 
 6 public class TransactionSource implements Callable<int[]> {
 7 
 8   public TransactionSource(TransactionType type, int maxTrans, Vector<Account> accounts, Vector<Clerk> clerks) {
 9     this.type = type;
10     this.maxTrans = maxTrans;
11     this.accounts = accounts;
12     this.clerks = clerks;
13     totals = new int[accounts.size()];
14   }
15 
16   // The source of transactions
17   public int[] call() {
18     // Create transactions randomly distributed between the accounts
19     Random rand = new Random();
20     Transaction transaction = null;                                    // Stores a transaction
21     int amount = 0;                                                    // Stores an amount of money
22     int select = 0;                                                    // Selects an account
23     boolean done = false;
24     for(int i = 1 ; i <= maxTrans ; ++i) {
25       // Generate a random account index for  operation
26       select = rand.nextInt(accounts.size());
27       amount = 50 + rand.nextInt(26);                                  // Generate amount of $50 to $75
28       transaction = new Transaction(accounts.get(select),              // Account
29                                     type,                              // Transaction type
30                                     amount);                           //  of amount
31       totals[select] += amount;                                        // Keep total tally for account
32       done = false;
33       while(true) {
34         // Find a clerk to do the transaction
35         for(Clerk clerk : clerks) {
36           if(done = clerk.doTransaction(transaction))
37             break;
38         }
39         if(done) {
40           break;
41         }
42 
43         // No clerk was free so wait a while
44         try {
45           Thread.sleep(10);
46         } catch(InterruptedException e) {
47           System.out.println(" TransactionSource
" + e);
48           return totals;
49         }
50       }
51       if(Thread.interrupted()) {
52         System.out.println("Interrupt flag for "+ type + " transaction source set. Terminating.");
53         return totals;
54       }
55     }
56     return totals;
57   }
58 
59   private TransactionType type;
60   private int maxTrans;
61   private Vector<Account> accounts;
62   private Vector<Clerk> clerks;
63   private int[] totals;
64 }
 1 import java.util.Vector;
 2 import java.util.concurrent.Executors;
 3 import java.util.concurrent.ExecutorService;
 4 import java.util.concurrent.Future;
 5 import java.util.concurrent.ExecutionException;
 6 import java.util.concurrent.TimeUnit;
 7 
 8 public class UsingExecutors {
 9 
10     public static void main(String[] args) {
11       int[] initialBalance = {500, 800};                               // The initial account balances
12       int[] totalCredits = new int[initialBalance.length];             // Two different cr totals
13       int[] totalDebits = new int[initialBalance.length];              // Two different db totals
14       int transactionCount = 20;                                       // Number of debits and of credits
15       int clerkCount = 2;
16 
17       // Create the account, the bank, and the clerks...
18       Bank theBank = new Bank();                                       // Create a bank
19       Vector<Clerk> clerks = new Vector<Clerk>();                      // Stores the clerk
20       Vector<Account> accounts = new Vector<Account>();                // Stores the accounts
21 
22       for(int i = 0 ; i < clerkCount ; ++i) {
23         clerks.add(new Clerk(i+1, theBank));                           // Create the clerks
24       }
25 
26       for(int i = 0 ; i < initialBalance.length; ++i) {
27         accounts.add(new Account(i+1, initialBalance[i]));             // Create accounts
28         totalCredits[i] = totalDebits[i] = 0;
29       }
30 
31       ExecutorService threadPool = Executors.newCachedThreadPool();
32 
33       // Create and start the transaction source threads
34       Future<int[]> credits = threadPool.submit(new TransactionSource(TransactionType.CREDIT, transactionCount, accounts, clerks));
35       Future<int[]> debits = threadPool.submit(new TransactionSource(TransactionType.DEBIT, transactionCount, accounts, clerks));
36 
37       // Create and start the clerk threads
38       for(Clerk clerk : clerks) {
39         threadPool.submit(clerk);
40       }
41       try {
42         totalCredits = credits.get();
43         totalDebits = debits.get();
44       } catch(ExecutionException e) {
45         System.out.println(e.getCause());
46       } catch(InterruptedException e) {
47         System.out.println(e);
48       }
49 
50     // Orderly shutdown when all threads have ended
51     threadPool.shutdown();
52     try {
53       threadPool.awaitTermination(10L, TimeUnit.SECONDS);
54     } catch(InterruptedException e) {
55       System.out.println(e);
56     }
57 
58     if(threadPool.isTerminated()) {
59       System.out.println("
All clerks have completed their tasks.
");
60     } else {
61       System.out.println("
Clerks still running - shutting down anyway.
");
62       threadPool.shutdownNow();
63     }
64 
65     // Now output the results
66     for(int i = 0 ; i < accounts.size() ; ++i) {
67       System.out.println("Account Number:"+accounts.get(i).getAccountNumber()+"
"+
68          "Original balance    : $" + initialBalance[i] + "
" +
69          "Total credits       : $" + totalCredits[i] + "
" +
70          "Total debits        : $" + totalDebits[i] + "
" +
71          "Final balance       : $" + accounts.get(i).getBalance() + "
" +
72          "Should be           : $" + (initialBalance[i]
73                                    + totalCredits[i]
74                                    - totalDebits[i]) + "
");
75     }
76   }
77 }
原文地址:https://www.cnblogs.com/mannixiang/p/3450334.html