Java基础之线程——管理线程同步代码块(BankOperation4)
控制台程序。
除了同步类对象的方法之外,还可以把程序中的语句或代码块制定为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基础之线程——管理线程同步代码块(BankOperation4)的更多相关文章
- “全栈2019”Java多线程第二十一章:同步代码块产生死锁的例子
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...
- “全栈2019”Java多线程第十八章:同步代码块双重判断详解
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...
- Java 基础 线程的Runnable接口 /线程的同步方法 /同步代码块
笔记: /**通过 Runnable接口来实现多线程 * 1. 创建一个实现runnable 接口的类 * 2. 在类中实现接口的run() 抽象方法 * 3. 创建一个runnable 接口实现类的 ...
- 线程执行synchronized同步代码块时再次重入该锁过程中抛异常,是否会释放锁
一个线程执行synchronized同步代码时,再次重入该锁过程中,如果抛出异常,会释放锁吗? 如果锁的计数器为1,抛出异常,会直接释放锁: 那如果锁的计数器为2,抛出异常,会直接释放锁吗? 来简单测 ...
- Android(java)学习笔记68:同步代码块 和 同步方法 的应用
1. 同步代码块 和 同步方法 代码示例: (1)目标类,如下: package cn.himi.text; public class SellTicket implements Runnable { ...
- Android(java)学习笔记8:同步代码块 和 同步方法 的应用
1. 同步代码块 和 同步方法 代码示例: (1)目标类,如下: package cn.himi.text; public class SellTicket implements Runnable { ...
- 【JAVA基础&Python】静态/非静态代码块
/* * * static静态代码块: * 调用静态属性的时候 对应类里面的静态代码块就会被直接执行 * 注意: 只会执行一次,只能调用类内静态结构的(方法/属性) * 作用: 初始化类的属性 * * ...
- JAVA基础知识之多线程——线程同步
线程安全问题 多个线程同时访问同一资源的时候有可能会出现信息不一致的情况,这是线程安全问题,下面是一个例子, Account.class , 定义一个Account模型 package threads ...
- 彻底理解线程同步与同步代码块synchronized
public class Demo { public static synchronized void fun1(){ } public synchronized void fun2(){ } pub ...
- 0037 Java学习笔记-多线程-同步代码块、同步方法、同步锁
什么是同步 在上一篇0036 Java学习笔记-多线程-创建线程的三种方式示例代码中,实现Runnable创建多条线程,输出中的结果中会有错误,比如一张票卖了两次,有的票没卖的情况,因为线程对象被多条 ...
随机推荐
- Ecshop的购物流程代码分析详细说明
Ecshop的购物流程代码分析详细说明 (2012-07-30 10:41:12) 转载▼ 标签: 购物车 结算中心 商品价格 ecshop ecshop购物流程 杂谈 分类: ECSHOP研究院 同 ...
- 20145225 实验四《Andoid开发基础》
实验内容 搭建Android环境 运行Android 修改代码,能输出学号 实验步骤 安装Android Studio 安装Android的SDK 运行Andriod Studio并在模拟手机上显示自 ...
- windows系统中ubuntu虚拟机安装及web项目到服务上(二)
ajp方式整合apache2和tomcat 7 1:在apache2.conf配置文件中启用模块mod_proxy_ajp,在里面添加 LoadModule proxy_module modules/ ...
- 如何去掉delphi2010的欢迎界面(welcome page)
如何去掉delphi2010的欢迎界面(welcome page)方法一: 在电脑开始菜单下,找到delphi的快捷菜单,点击该菜单的属性,在“目标”的内容中,最后添加“-np”即可.如:D:\Win ...
- Android App罕见错误和优化方案
本文来自http://blog.csdn.net/liuxian13183/ ,引用必须注明出处! 1.App如果被定义一个有参数构造函数,那么需要再定义一个无参数的,如果不则会在某些情况下初始化失败 ...
- 应中DOS中断显示字符串(摘自《汇编语言》王爽)
data segment s1 db 'Good,better,best,$' s2 db 'Never let it rest,$' s3 db 'Till good is better,$' s4 ...
- css背景图片定位练习(二): background-position的百分比
background-position:x y; 百分比定位并不能直观的看出来,需要通过计算. background-position百分比计算公式: (容器宽度—背景图片的宽度)*x%=xpx(容器 ...
- 雾里看花终隔一层——探析package和import
package是什么 package好比java用来组织文件的一种虚拟文件系统.package把源代码.java文件,.class文件和其他文件有条理的进行一个组织,以供java来使用. 源代码的要求 ...
- Selenium2学习-028-WebUI自动化实战实例-026-获取页面元素值或者元素属性值
在自动化脚本编写过程中,经常需要获取页面元素的文本进行判断,以便对于不同的文本进行不同的处理.比如:很多的购物网站,加入购物车的按钮是有多个状态的(加入购物车.到货通知.暂不销售等),那么在实际的操作 ...
- js的执行顺序
js是顺序执行的,但是在一个<script></script>标签中,后面的函数会预加载.如: <script type="text/javascript&qu ...