控制台程序。

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

  1. // Defines a customer account
  2. public class Account {
  3. // Constructor
  4. public Account(int accountNumber, int balance) {
  5. this.accountNumber = accountNumber; // Set the account number
  6. this.balance = balance; // Set the initial balance
  7. }
  8.  
  9. // Return the current balance
  10. public int getBalance() {
  11. return balance;
  12. }
  13.  
  14. // Set the current balance
  15. public void setBalance(int balance) {
  16. this.balance = balance;
  17. }
  18.  
  19. public int getAccountNumber() {
  20. return accountNumber;
  21. }
  22.  
  23. @Override
  24. public String toString() {
  25. return "A/C No. " + accountNumber + " : $" + balance;
  26. }
  27.  
  28. private int balance; // The current account balance
  29. private int accountNumber; // Identifies this account
  30. }
  1. // Bank account transaction types
  2. public enum TransactionType {DEBIT, CREDIT }
  1. public class Transaction {
  2. // Constructor
  3. public Transaction(Account account, TransactionType type, int amount) {
  4. this.account = account;
  5. this.type = type;
  6. this.amount = amount;
  7. }
  8.  
  9. public Account getAccount() {
  10. return account;
  11. }
  12.  
  13. public TransactionType getTransactionType() {
  14. return type;
  15. }
  16.  
  17. public int getAmount() {
  18. return amount;
  19. }
  20. @Override
  21. public String toString() {
  22. return type + " A//C: " + account + ": $" + amount;
  23. }
  24.  
  25. private Account account;
  26. private int amount;
  27. private TransactionType type;
  28. }
  1. // Define the bank
  2.  
  3. public class Bank {
  4. // Perform a transaction
  5. public void doTransaction(Transaction transaction) {
  6. switch(transaction.getTransactionType()) {
  7. case CREDIT:
  8. synchronized(transaction.getAccount()) {
  9. System.out.println("Start credit of " +
  10. transaction.getAccount() + " amount: " +
  11. transaction.getAmount());
  12.  
  13. // Get current balance
  14. int balance = transaction.getAccount().getBalance();
  15.  
  16. // Credits require a lot of checks...
  17. try {
  18. Thread.sleep(100);
  19.  
  20. } catch(InterruptedException e) {
  21. System.out.println(e);
  22. }
  23. balance += transaction.getAmount(); // Increment the balance
  24. transaction.getAccount().setBalance(balance); // Restore account balance
  25. System.out.println(" End credit of " +
  26. transaction.getAccount() + " amount: " +
  27. transaction.getAmount());
  28. break;
  29. }
  30. case DEBIT:
  31. synchronized(transaction.getAccount()) {
  32. System.out.println("Start debit of " +
  33. transaction.getAccount() + " amount: " +
  34. transaction.getAmount());
  35.  
  36. // Get current balance
  37. int balance = transaction.getAccount().getBalance();
  38.  
  39. // Debits require even more checks...
  40. try {
  41. Thread.sleep(150);
  42.  
  43. } catch(InterruptedException e) {
  44. System.out.println(e);
  45. }
  46. balance -= transaction.getAmount(); // Decrement the balance...
  47. transaction.getAccount().setBalance(balance); // Restore account balance
  48.  
  49. System.out.println(" End debit of " +
  50. transaction.getAccount() + " amount: " +
  51. transaction.getAmount());
  52. break;
  53. }
  54.  
  55. default: // We should never get here
  56. System.out.println("Invalid transaction");
  57. System.exit(1);
  58. }
  59. }
  60. }
  1. public class Clerk implements Runnable {
  2. // Constructor
  3. public Clerk(Bank theBank) {
  4. this.theBank = theBank; // Who the clerk works for
  5. inTray = null; // No transaction initially
  6. }
  7.  
  8. // Receive a transaction
  9. public void doTransaction(Transaction transaction) {
  10. inTray = transaction;
  11. }
  12.  
  13. // The working clerk...
  14. public void run() {
  15. while(true) { // Non-stop work...
  16. while(inTray == null) { // No transaction waiting?
  17. try {
  18. Thread.sleep(150); // Then take a break...
  19.  
  20. } catch(InterruptedException e) {
  21. System.out.println(e);
  22. }
  23. }
  24.  
  25. theBank.doTransaction(inTray);
  26. inTray = null; // In-tray is empty
  27. }
  28. }
  29.  
  30. // Busy check
  31. public boolean isBusy() {
  32. return inTray != null; // A full in-tray means busy!
  33. }
  34.  
  35. private Bank theBank; // The employer - an electronic marvel
  36. private Transaction inTray; // The in-tray holding a transaction
  37. }
  1. import java.util.Random;
  2.  
  3. public class BankOperation4 {
  4. public static void main(String[] args) {
  5. int[] initialBalance = {500, 800}; // The initial account balances
  6. int[] totalCredits = new int[initialBalance.length]; // Two different cr totals
  7. int[] totalDebits = new int[initialBalance.length]; // Two different db totals
  8. int transactionCount = 20; // Number of debits and of credits
  9.  
  10. // Create the account, the bank, and the clerks...
  11. Bank theBank = new Bank(); // Create a bank
  12. Clerk clerk1 = new Clerk(theBank); // Create the first clerk
  13. Clerk clerk2 = new Clerk(theBank); // Create the second clerk
  14.  
  15. // Create the accounts, and initialize total credits and debits
  16. Account[] accounts = new Account[initialBalance.length];
  17. for(int i = 0 ; i < initialBalance.length ; ++i) {
  18. accounts[i] = new Account(i+1, initialBalance[i]); // Create accounts
  19. totalCredits[i] = totalDebits[i] = 0;
  20. }
  21. // Create the threads for the clerks as daemon, and start them off
  22. Thread clerk1Thread = new Thread(clerk1);
  23. Thread clerk2Thread = new Thread(clerk2);
  24. clerk1Thread.setDaemon(true); // Set first as daemon
  25. clerk2Thread.setDaemon(true); // Set second as daemon
  26. clerk1Thread.start(); // Start the first
  27. clerk2Thread.start(); // Start the second
  28.  
  29. // Create transactions randomly distributed between the accounts
  30. Random rand = new Random();
  31. Transaction transaction; // Stores a transaction
  32. int amount = 0; // Stores an amount of money
  33. int select = 0; // Selects an account
  34. for(int i = 1; i <= transactionCount; i++) {
  35. // Choose an account at random for credit operation
  36. select = rand.nextInt(accounts.length);
  37. amount = 50 + rand.nextInt(26); // Generate amount of $50 to $75
  38. transaction = new Transaction(accounts[select], // Account
  39. TransactionType.CREDIT, // Credit transaction
  40. amount); // of amount
  41. totalCredits[select] += amount; // Keep total credit tally
  42.  
  43. // Wait until the first clerk is free
  44. while(clerk1.isBusy()) {
  45. try {
  46. Thread.sleep(25); // Busy so try later
  47. } catch(InterruptedException e) {
  48. System.out.println(e);
  49. }
  50. }
  51. clerk1.doTransaction(transaction); // Now do the credit
  52.  
  53. // choose an account at random for debit operation
  54. select = rand.nextInt(accounts.length);
  55. amount = 30 + rand.nextInt(31); // Generate amount of $30 to $60
  56. transaction = new Transaction(accounts[select], // Account
  57. TransactionType.DEBIT, // Debit transaction
  58. amount); // of amount
  59. totalDebits[select] += amount; // Keep total debit tally
  60.  
  61. // Wait until the second clerk is free
  62. while(clerk2.isBusy()) {
  63. try {
  64. Thread.sleep(25); // Busy so try later
  65. } catch(InterruptedException e) {
  66. System.out.println(e);
  67. }
  68. }
  69. clerk2.doTransaction(transaction); // Now do the debit
  70. }
  71.  
  72. // Wait until both clerks are done
  73. while(clerk1.isBusy() || clerk2.isBusy()) {
  74. try {
  75. Thread.sleep(25);
  76.  
  77. } catch(InterruptedException e) {
  78. System.out.println(e);
  79. }
  80. }
  81.  
  82. // Now output the results
  83. for(int i = 0; i < accounts.length; ++i) {
  84. System.out.println("Account Number:"+accounts[i].getAccountNumber()+"\n"+
  85. "Original balance : $" + initialBalance[i] + "\n" +
  86. "Total credits : $" + totalCredits[i] + "\n" +
  87. "Total debits : $" + totalDebits[i] + "\n" +
  88. "Final balance : $" + accounts[i].getBalance() + "\n" +
  89. "Should be : $" + (initialBalance[i]
  90. + totalCredits[i]
  91. - totalDebits[i]) + "\n");
  92. }
  93. }
  94. }

synchronized关键字后面圆括号中的表达式用来指定要同步的对象。一旦执行到给定账户对象的同步代码块,就不能再执行为这个账户对象同步的其他代码块或方法。例如,如果用事务的getAccount()方法返回的account[1]对象来引用进行贷款处理的代码块,就不能再执行这个对象的借款处理代码块,但可以执行其他对象的借款处理代码块。

Java基础之线程——管理线程同步代码块(BankOperation4)的更多相关文章

  1. “全栈2019”Java多线程第二十一章:同步代码块产生死锁的例子

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...

  2. “全栈2019”Java多线程第十八章:同步代码块双重判断详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...

  3. Java 基础 线程的Runnable接口 /线程的同步方法 /同步代码块

    笔记: /**通过 Runnable接口来实现多线程 * 1. 创建一个实现runnable 接口的类 * 2. 在类中实现接口的run() 抽象方法 * 3. 创建一个runnable 接口实现类的 ...

  4. 线程执行synchronized同步代码块时再次重入该锁过程中抛异常,是否会释放锁

    一个线程执行synchronized同步代码时,再次重入该锁过程中,如果抛出异常,会释放锁吗? 如果锁的计数器为1,抛出异常,会直接释放锁: 那如果锁的计数器为2,抛出异常,会直接释放锁吗? 来简单测 ...

  5. Android(java)学习笔记68:同步代码块 和 同步方法 的应用

    1. 同步代码块 和 同步方法 代码示例: (1)目标类,如下: package cn.himi.text; public class SellTicket implements Runnable { ...

  6. Android(java)学习笔记8:同步代码块 和 同步方法 的应用

    1. 同步代码块 和 同步方法 代码示例: (1)目标类,如下: package cn.himi.text; public class SellTicket implements Runnable { ...

  7. 【JAVA基础&Python】静态/非静态代码块

    /* * * static静态代码块: * 调用静态属性的时候 对应类里面的静态代码块就会被直接执行 * 注意: 只会执行一次,只能调用类内静态结构的(方法/属性) * 作用: 初始化类的属性 * * ...

  8. JAVA基础知识之多线程——线程同步

    线程安全问题 多个线程同时访问同一资源的时候有可能会出现信息不一致的情况,这是线程安全问题,下面是一个例子, Account.class , 定义一个Account模型 package threads ...

  9. 彻底理解线程同步与同步代码块synchronized

    public class Demo { public static synchronized void fun1(){ } public synchronized void fun2(){ } pub ...

  10. 0037 Java学习笔记-多线程-同步代码块、同步方法、同步锁

    什么是同步 在上一篇0036 Java学习笔记-多线程-创建线程的三种方式示例代码中,实现Runnable创建多条线程,输出中的结果中会有错误,比如一张票卖了两次,有的票没卖的情况,因为线程对象被多条 ...

随机推荐

  1. Unity 中 使用c#线程

    使用条件   天下没有免费的午餐,在我使用unity的那一刻,我就感觉到不自在,因为开源所以不知道底层实现,如果只是简单的做点简单游戏,那就无所谓的了,但真正用到实际地方的时候,就会发现一个挨着一个坑 ...

  2. 初步理解Java的三大特性——封装、继承和多态

    声明:整理自网络,如有雷同,请联系博主处理 一.封装 封装从字面上来理解就是包装的意思,专业点就是信息隐藏,是指利用抽象数据类型将数据和基于数据的操作封装在一起,使其构成一个不可分割的独立实体,数据被 ...

  3. Apache Kafka源码分析 - KafkaApis

    kafka apis反映出kafka broker server可以提供哪些服务,broker server主要和producer,consumer,controller有交互,搞清这些api就清楚了 ...

  4. DML以及DQL的使用方法

    DML:数据操作语言 1.插入insert into 单行插入:insert into 表名 (字段名, 字段名,...) values (值, 值, ...) 注:值列表要和字段列表相匹配. ins ...

  5. selenium By 元素定位详解

    转自:http://blog.sina.com.cn/s/blog_6966650401012a6u.html WebDriver拾级而上·之三 定位页面元素 selenium-webdriver提供 ...

  6. (转)js一道比较考验的题目

    转载下别人曾经出过的一道面试题,此题是他出的一套前端面试题中的最后一题,用来考核面试者的JavaScript的综合能力,很可惜到目前为止的将近两年中,几乎没有人能够完全答对,并非多难只是因为大多面试者 ...

  7. Redis学习笔记(5)-Set

    package cn.com; import java.util.HashMap; import java.util.Map; import java.util.Set; import redis.c ...

  8. X-UA-Compatible是神马

    X-UA-Compatible是神马 X-UA-Compatible是IE8的一个专有<meta>属性,它告诉IE8采用何种IE版本去渲染网页,在html的<head>标签中使 ...

  9. C++ TrieTree(字典树)容器的实现

    最近研究了一下C++线程池,在网上看了一下别人的代码,写的很不错,参见:http://www.cnblogs.com/lidabo/p/3328646.html 其中,他用了STL的set容器管理线程 ...

  10. php--数据库三范式

    关系数据库的几种设计范式介绍1.第一范式(1NF) 在任何一个关系数据库中,第一范式(1NF)是对关系模式的基本要求,不满足第一范式(1NF)的数据库就不是关系数据库. 所谓第一范式(1NF)是指数据 ...