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创建多条线程,输出中的结果中会有错误,比如一张票卖了两次,有的票没卖的情况,因为线程对象被多条 ...
随机推荐
- php中ajax跨域请求---小记
php中ajax跨域请求---小记 前端时间,遇到的一个问题,情况大约是这样: 原来的写法: 前端js文件中: $.ajax({ type:'get', url:'http://wan.xxx.c ...
- 1763 An Essay towards solving a Problem in the Doctrine of Chances
https://en.wikipedia.org/wiki/An_Essay_towards_solving_a_Problem_in_the_Doctrine_of_Chances
- java RMI
import java.rmi.*; public interface Hello extends Remote { public String getGreeting() throws Remote ...
- SQLServer2008:助您轻松编写T-SQL存储过程(原创)【转】
本文主要介绍 SQLServerExpress2008不用第三方工具调试T-SQL语句,经过本文的介绍,用SQLSERVER2008 Manage studio 编写.调试T-SQL存储过程都将是 ...
- sql 语句查询练习题
1. 查询Student表中的所有记录的Sname.Ssex和Class列. select sname,ssex,class from student 2. 查询教师所有的单位即不重复的Depart列 ...
- Bluetooth Baseband介绍
目录 1. 概述 1.1 Clock(时钟) 1.2 寻址方式 2. 物理信道(Physical Channels) 3. 物理链路(Physical Links) 4. 逻辑传输层(Logical ...
- 蓝牙HID协议笔记
1.概述 The Human Interface Device (HID)定义了蓝牙在人机接口设备中的协议.特征和使用规程.典型的应用包括蓝牙鼠标.蓝牙键盘.蓝牙游戏手柄等.该协议改编自USB ...
- maven--composer---setting.xml(updatepolicy)---mvn install , mvn deploy
场景:最近再整系统的自动部署流程,由于公司的jar包在svn以及mvn的仓库上都存在,开发人员在开发的过程中都依赖mvn仓库中的Jar 包,在jar上线的时候,配置管理人员把jar 从svn管理的工作 ...
- centos常用命令
应用程序->附件->终端 一:使用CentOS常用命令查看cpumore /proc/cpuinfo | grep "model name" grep " ...
- FastDFS分布式文件系统安装与使用(单节点)
http://blog.csdn.net/xyang81/article/details/52837974 http://download.csdn.net/detail/xyang81/966749 ...