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创建多条线程,输出中的结果中会有错误,比如一张票卖了两次,有的票没卖的情况,因为线程对象被多条 ...
随机推荐
- Unity 中 使用c#线程
使用条件 天下没有免费的午餐,在我使用unity的那一刻,我就感觉到不自在,因为开源所以不知道底层实现,如果只是简单的做点简单游戏,那就无所谓的了,但真正用到实际地方的时候,就会发现一个挨着一个坑 ...
- 初步理解Java的三大特性——封装、继承和多态
声明:整理自网络,如有雷同,请联系博主处理 一.封装 封装从字面上来理解就是包装的意思,专业点就是信息隐藏,是指利用抽象数据类型将数据和基于数据的操作封装在一起,使其构成一个不可分割的独立实体,数据被 ...
- Apache Kafka源码分析 - KafkaApis
kafka apis反映出kafka broker server可以提供哪些服务,broker server主要和producer,consumer,controller有交互,搞清这些api就清楚了 ...
- DML以及DQL的使用方法
DML:数据操作语言 1.插入insert into 单行插入:insert into 表名 (字段名, 字段名,...) values (值, 值, ...) 注:值列表要和字段列表相匹配. ins ...
- selenium By 元素定位详解
转自:http://blog.sina.com.cn/s/blog_6966650401012a6u.html WebDriver拾级而上·之三 定位页面元素 selenium-webdriver提供 ...
- (转)js一道比较考验的题目
转载下别人曾经出过的一道面试题,此题是他出的一套前端面试题中的最后一题,用来考核面试者的JavaScript的综合能力,很可惜到目前为止的将近两年中,几乎没有人能够完全答对,并非多难只是因为大多面试者 ...
- Redis学习笔记(5)-Set
package cn.com; import java.util.HashMap; import java.util.Map; import java.util.Set; import redis.c ...
- X-UA-Compatible是神马
X-UA-Compatible是神马 X-UA-Compatible是IE8的一个专有<meta>属性,它告诉IE8采用何种IE版本去渲染网页,在html的<head>标签中使 ...
- C++ TrieTree(字典树)容器的实现
最近研究了一下C++线程池,在网上看了一下别人的代码,写的很不错,参见:http://www.cnblogs.com/lidabo/p/3328646.html 其中,他用了STL的set容器管理线程 ...
- php--数据库三范式
关系数据库的几种设计范式介绍1.第一范式(1NF) 在任何一个关系数据库中,第一范式(1NF)是对关系模式的基本要求,不满足第一范式(1NF)的数据库就不是关系数据库. 所谓第一范式(1NF)是指数据 ...