Java基础之线程——管理线程同步代码块(BankOperation4)
2013-11-27 23:16
337 查看
控制台程序。
除了同步类对象的方法之外,还可以把程序中的语句或代码块制定为synchronized,这种方式更强大,因为可以指定哪个对象从语句或代码块的同步中获益,而不像同步方法那样仅仅是包含代码的对象能获益。这里可以对给定代码块的任何对象设置锁。当对给定对象执行同步的代码块时,就不能执行对相同对象同步的其他代码或方法。
synchronized关键字后面圆括号中的表达式用来指定要同步的对象。一旦执行到给定账户对象的同步代码块,就不能再执行为这个账户对象同步的其他代码块或方法。例如,如果用事务的getAccount()方法返回的account[1]对象来引用进行贷款处理的代码块,就不能再执行这个对象的借款处理代码块,但可以执行其他对象的借款处理代码块。
除了同步类对象的方法之外,还可以把程序中的语句或代码块制定为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]对象来引用进行贷款处理的代码块,就不能再执行这个对象的借款处理代码块,但可以执行其他对象的借款处理代码块。
相关文章推荐
- Java基础之线程——管理线程同步方法(BankOperation2)
- Java多线程基础篇(04)-线程同步机制和线程间通信
- 黑马程序员_java基础笔记(14)...交通灯管理系统_编码思路及代码
- 【Java基础之线程同步(二)】java线程同步:synchronized关键字,Lock接口以及可重入锁ReentrantLock
- Java并发编程之线程管理(高级线程同步7)
- java-线程管理基础
- Java并发编程之线程管理(基本线程同步5)
- JAVA基础代码分享--学生成绩管理
- 深入Java线程管理(三):线程同步
- 深入Java线程管理(三):线程同步
- Java并发编程之线程管理(基本线程同步2)
- java基础总结24-java线程2(线程同步)
- 黑马程序员_java基础笔记(14)...交通灯管理系统_编码思路及代码
- Java并发编程之线程管理(高级线程同步8)
- Java并发之线程管理(线程基础知识)
- Java 2 入门经典(线程、线程同步示例代码)
- 黑马程序员-----java基础二十三(交通灯管理方案代码实现)
- Java并发编程之线程管理(高级线程同步10)
- 黑马程序员-----java基础二十四(银行柜台取票管理方案代码实现)
- Java并发编程之线程管理(基本线程同步4)