您的位置:首页 > 编程语言 > Java开发

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

2013-11-27 23:16 337 查看
控制台程序。

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

// Defines a customer account
public class Account {
// Constructor
public Account(int accountNumber, int balance) {
this.accountNumber = accountNumber;                                // Set the account number
this.balance = balance;                                            // Set the initial balance
}

// Return the current balance
public int getBalance() {
return balance;
}

// Set the current balance
public void setBalance(int balance) {
this.balance = balance;
}

public int getAccountNumber() {
return accountNumber;
}

@Override
public String toString() {
return "A/C No. " + accountNumber + " : $" + balance;
}

private int balance;                                                 // The current account balance
private int accountNumber;                                           // Identifies this account
}


// Bank account transaction types
public enum TransactionType {DEBIT, CREDIT }


public class Transaction {
// Constructor
public Transaction(Account account, TransactionType type, int amount) {
this.account = account;
this.type = type;
this.amount = amount;
}

public Account getAccount() {
return account;
}

public TransactionType getTransactionType() {
return type;
}

public int getAmount() {
return amount;
}
@Override
public String toString() {
return type + " A//C: " + account + ": $" + amount;
}

private Account account;
private int amount;
private TransactionType type;
}


// Define the bank

public class Bank {
// Perform a transaction
public void doTransaction(Transaction transaction) {
switch(transaction.getTransactionType()) {
case CREDIT:
synchronized(transaction.getAccount()) {
System.out.println("Start credit of " +
transaction.getAccount() + " amount: " +
transaction.getAmount());

// Get current balance
int balance = transaction.getAccount().getBalance();

// Credits require a lot of checks...
try {
Thread.sleep(100);

} catch(InterruptedException e) {
System.out.println(e);
}
balance += transaction.getAmount();                          // Increment the balance
transaction.getAccount().setBalance(balance);                // Restore account balance
System.out.println("  End credit of " +
transaction.getAccount() + " amount: " +
transaction.getAmount());
break;
}
case DEBIT:
synchronized(transaction.getAccount()) {
System.out.println("Start debit of " +
transaction.getAccount() + " amount: " +
transaction.getAmount());

// Get current balance
int balance = transaction.getAccount().getBalance();

// Debits require even more checks...
try {
Thread.sleep(150);

} catch(InterruptedException e) {
System.out.println(e);
}
balance -= transaction.getAmount();                          // Decrement the balance...
transaction.getAccount().setBalance(balance);                // Restore account balance

System.out.println("  End debit of " +
transaction.getAccount() + " amount: " +
transaction.getAmount());
break;
}

default:                                                         // We should never get here
System.out.println("Invalid transaction");
System.exit(1);
}
}
}


public class Clerk implements Runnable {
// Constructor
public Clerk(Bank theBank) {
this.theBank = theBank;                                            // Who the clerk works for
inTray = null;                                                     // No transaction initially
}

// Receive a transaction
public void doTransaction(Transaction transaction) {
inTray = transaction;
}

// The working clerk...
public void run() {
while(true) {                                                      // Non-stop work...
while(inTray == null) {                                          // No transaction waiting?
try {
Thread.sleep(150);                                           // Then take a break...

} catch(InterruptedException e) {
System.out.println(e);
}
}

theBank.doTransaction(inTray);
inTray = null;                                                   // In-tray is empty
}
}

// Busy check
public boolean isBusy() {
return inTray != null;                                             // A full in-tray means busy!
}

private Bank theBank;                                                // The employer - an electronic marvel
private Transaction inTray;                                          // The in-tray holding a transaction
}


import java.util.Random;

public class BankOperation4 {
public static void main(String[] args) {
int[] initialBalance = {500, 800};                                 // The initial account balances
int[] totalCredits = new int[initialBalance.length];               // Two different cr totals
int[] totalDebits = new int[initialBalance.length];                // Two different db totals
int transactionCount = 20;                                         // Number of debits and of credits

// Create the account, the bank, and the clerks...
Bank theBank = new Bank();                                         // Create a bank
Clerk clerk1 = new Clerk(theBank);                                 // Create the first clerk
Clerk clerk2 = new Clerk(theBank);                                 // Create the second clerk

// Create the accounts, and initialize total credits and debits
Account[] accounts = new Account[initialBalance.length];
for(int i = 0 ; i < initialBalance.length ; ++i) {
accounts[i] = new Account(i+1, initialBalance[i]);               // Create accounts
totalCredits[i] = totalDebits[i] = 0;
}
// Create the threads for the clerks as daemon, and start them off
Thread clerk1Thread = new Thread(clerk1);
Thread clerk2Thread = new Thread(clerk2);
clerk1Thread.setDaemon(true);                                      // Set first as daemon
clerk2Thread.setDaemon(true);                                      // Set second as daemon
clerk1Thread.start();                                              // Start the first
clerk2Thread.start();                                              // Start the second

// Create transactions randomly distributed between the accounts
Random rand = new Random();
Transaction transaction;                                           // Stores a transaction
int amount = 0;                                                    // Stores an amount of money
int select = 0;                                                    // Selects an account
for(int i = 1; i <= transactionCount; i++) {
// Choose an account at random for credit operation
select = rand.nextInt(accounts.length);
amount = 50 + rand.nextInt(26);                                  // Generate amount of $50 to $75
transaction = new Transaction(accounts[select],                  // Account
TransactionType.CREDIT,                  // Credit transaction
amount);                           //  of amount
totalCredits[select] += amount;                                  // Keep total credit tally

// Wait until the first clerk is free
while(clerk1.isBusy()) {
try {
Thread.sleep(25);                                            // Busy so try later
} catch(InterruptedException e) {
System.out.println(e);
}
}
clerk1.doTransaction(transaction);                               // Now do the credit

// choose an account at random for debit operation
select = rand.nextInt(accounts.length);
amount = 30 + rand.nextInt(31);                                  // Generate amount of $30 to $60
transaction = new Transaction(accounts[select],                  // Account
TransactionType.DEBIT,                   // Debit transaction
amount);                           //  of amount
totalDebits[select] += amount;                                   // Keep total debit tally

// Wait until the second clerk is free
while(clerk2.isBusy()) {
try {
Thread.sleep(25);                                            // Busy so try later
} catch(InterruptedException e) {
System.out.println(e);
}
}
clerk2.doTransaction(transaction);                               // Now do the debit
}

// Wait until both clerks are done
while(clerk1.isBusy() || clerk2.isBusy()) {
try {
Thread.sleep(25);

} catch(InterruptedException e) {
System.out.println(e);
}
}

// Now output the results
for(int i = 0; i < accounts.length; ++i) {
System.out.println("Account Number:"+accounts[i].getAccountNumber()+"\n"+
"Original balance    : $" + initialBalance[i] + "\n" +
"Total credits       : $" + totalCredits[i] + "\n" +
"Total debits        : $" + totalDebits[i] + "\n" +
"Final balance       : $" + accounts[i].getBalance() + "\n" +
"Should be           : $" + (initialBalance[i]
+ totalCredits[i]
- totalDebits[i]) + "\n");
}
}
}


synchronized关键字后面圆括号中的表达式用来指定要同步的对象。一旦执行到给定账户对象的同步代码块,就不能再执行为这个账户对象同步的其他代码块或方法。例如,如果用事务的getAccount()方法返回的account[1]对象来引用进行贷款处理的代码块,就不能再执行这个对象的借款处理代码块,但可以执行其他对象的借款处理代码块。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: