• 线程通信(案例)


    什么是线程通信、如何实现?

    所谓线程通信就是线程之间相互发送数据,线程通信通常通过共享一个数据的方式实现

    线程之间会根据共享数据的情况决定自己改怎么做,以及通知其他线程怎么做

    线程通信的常见模型

    生产者与消费者模型:生产者线程负责生产数据,消费者线程负责消费数据

    要求:生产者线程生产完数据后,唤醒消费者,然后等待自己,消费者消费完数据后,唤醒生产者,然后等待自己

    线程通信常用三个方法

    void wait() 当前线程等待,直到另一个线程调用notify()或者notiyall() 唤醒自己

    void  notify ( ) 唤醒正在等待对象监听器(锁对象) 的单个线程

    void notifyAll() 唤醒正在等待对选哪个监听器(锁对象)的多个线程

    注意:上述方法应当使用同步锁对象进行调用

    案例模拟

    一个家庭中,A和B在银行负责存钱,C,D,E在银行中负责取钱。(每次都是整存整取,有钱就不需要存,等待取钱后才可以继续存钱)

    账户类(要公用一个账户)

    1. package 线程通信案例;
    2. /**
    3. * 账户类
    4. */
    5. public class Account {
    6. private String cardID;
    7. private double money;
    8. /**
    9. * @return the cardID
    10. */
    11. public String getCardID() {
    12. return cardID;
    13. }
    14. /**
    15. * @param cardID the cardID to set
    16. */
    17. public void setCardID(String cardID) {
    18. this.cardID = cardID;
    19. }
    20. /**
    21. * @return the money
    22. */
    23. public double getMoney() {
    24. return money;
    25. }
    26. /**
    27. * @param money the money to set
    28. */
    29. public void setMoney(double money) {
    30. this.money = money;
    31. }
    32. public Account(String cardID, double money) {
    33. super();
    34. this.cardID = cardID;
    35. this.money = money;
    36. }
    37. public Account() {
    38. super();
    39. }
    40. /**
    41. * 取钱方法多线程通信需要加锁
    42. * @param money
    43. */
    44. public synchronized void draw(Double money) {
    45. // TODO Auto-generated method stub
    46. String name=Thread.currentThread().getName(); //当前线程是谁就获取谁的线程名称
    47. try {
    48. if (this.money >= money) {
    49. //有钱可以取钱
    50. this.money -= money;
    51. System.out.println(name + "来取钱" +money+"卡内还剩"+this.money);
    52. this.notifyAll();
    53. this.wait();
    54. } else {
    55. }
    56. } catch (Exception e) {
    57. e.printStackTrace();
    58. }
    59. }
    60. /**
    61. * 存钱方法
    62. */
    63. public synchronized void deposit(double money) {
    64. // TODO Auto-generated method stub
    65. String name=Thread.currentThread().getName();
    66. try {
    67. if (this.money == 0) {
    68. //没有钱才会存钱
    69. this.money += money;
    70. System.out.println(name + "来存钱" +money+"卡内还剩"+ this.money);
    71. this.notifyAll();
    72. this.wait();
    73. } else {
    74. this.notifyAll();
    75. this.wait();
    76. }
    77. } catch (Exception e) {
    78. e.printStackTrace();
    79. }
    80. }
    81. }

    取钱线程

    1. package 线程通信案例;
    2. /**
    3. * 取钱线程
    4. * @author ASUS
    5. *
    6. */
    7. public class DrawMoneyThread extends Thread {
    8. Account account;
    9. //提供一个构造器
    10. public DrawMoneyThread(Account account ,String name) {
    11. super(name);
    12. this.account=account;
    13. }
    14. @Override
    15. public void run() {
    16. // TODO Auto-generated method stub
    17. while (true) {
    18. account.draw(10000.0);//整存整取
    19. try {
    20. Thread.sleep(3000);
    21. } catch (InterruptedException e) {
    22. // TODO Auto-generated catch block
    23. e.printStackTrace();
    24. }
    25. }
    26. }
    27. }

    存钱线程

    1. package 线程通信案例;
    2. /**
    3. * 存钱线程
    4. */
    5. public class DepositThread extends Thread{
    6. Account account;
    7. public DepositThread(Account account,String name) {
    8. super(name);
    9. this.account=account;
    10. }
    11. @Override
    12. public void run() {
    13. // TODO Auto-generated method stub
    14. while (true) {
    15. account.deposit(10000.0);
    16. try {
    17. Thread.sleep(3000);
    18. } catch (Exception e) {
    19. e.printStackTrace();
    20. }
    21. }
    22. }
    23. }

    测试一下

    1. package 线程通信案例;
    2. public class Teat {
    3. public static void main(String[] args) {
    4. //创建卡号
    5. Account ac=new Account("AA_001",0);
    6. //线程通信要用同一对象
    7. // 创建两个取钱线程
    8. new DrawMoneyThread(ac,"取钱A").start();
    9. new DrawMoneyThread(ac, "取钱B").start();
    10. //创建3个存钱线程
    11. new DepositThread(ac,"存钱C").start();
    12. new DepositThread(ac, "存钱D").start();
    13. new DepositThread(ac, "存钱E").start();
    14. }
    15. }

     

    输出的一直都是(随机的)

    存钱C来存钱10000.0卡内还剩10000.0
    取钱B来取钱10000.0卡内还剩0.0
    存钱E来存钱10000.0卡内还剩10000.0
    取钱A来取钱10000.0卡内还剩0.0
    存钱C来存钱10000.0卡内还剩10000.0
    取钱B来取钱10000.0卡内还剩0.0
    存钱C来存钱10000.0卡内还剩10000.0
    取钱A来取钱10000.0卡内还剩0.0
    存钱C来存钱10000.0卡内还剩10000.0
    取钱B来取钱10000.0卡内还剩0.0
    存钱D来存钱10000.0卡内还剩10000.0
    取钱A来取钱10000.0卡内还剩0.0
    存钱C来存钱10000.0卡内还剩10000.0
    取钱B来取钱10000.0卡内还剩0.0
    存钱D来存钱10000.0卡内还剩10000.0
    取钱A来取钱10000.0卡内还剩0.0
    存钱C来存钱10000.0卡内还剩10000.0
    取钱B来取钱10000.0卡内还剩0.0
     

  • 相关阅读:
    卷麻了,00后测试用例写的比我还好,简直无地自容......
    C++ 基础入门 之 结构体/结构体定义和使用/结构体数组/结构体指针/ 结构体嵌套结构体/结构体做函数参数/结构体中 const 使用场景/结构体案例
    Abbexa丨Abbexa 脱落酸 (ABA) ELISA试剂盒方案
    组件的使用
    python每日一题【剑指 Offer 48. 最长不含重复字符的子字符串】
    虚幻引擎:RPC:远端调用
    Programming internal SRAM over SWD
    已超1000+测试员分享!Python自动化测试案例实战
    Mybatis中的动态SQL
    MongoDB--- 客户端操作 与 复制集
  • 原文地址:https://blog.csdn.net/m0_64365315/article/details/125904402