JAVA对两个数计算加减乘除的结果

不能用if
不能用while
用变量做出来
学到后面把前面的只是丢了
不需要它一次全部性显示出来😩
做到这里,我就蒙了

img

这些很基础的,应该边学边练,平时多练习,自然就不会丢了。

  • 你可以参考下这个问题的回答, 看看是否对你有帮助, 链接: https://ask.csdn.net/questions/7661655
  • 这篇博客你也可以参考下:Java多线程同步操作中为什么要用 while 而不是 if
  • 除此之外, 这篇博客: 逐步详细分析Java生产者-消费者问题,为什么使用 while 而不用 if ?中的 存钱-取钱 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
  • 1、一个人存钱,一个人取钱:在卡中没钱的时候存钱,有钱的时候取钱,交替执行

    • flag为true时:只能取钱,存钱会被阻塞

    • flag为false时:只能存钱,取钱会被阻塞

    public class BankCard {
        private double money;
    
        // true:只能取钱
        private boolean flag;
    
        public synchronized void save(double addMoney) {
            if (flag) {
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            money += addMoney;
            System.out.println(Thread.currentThread().getName() + " 存了:" + addMoney + " 余额:" + money);
            flag = true;
            this.notify();
        }
        public synchronized void take(double takeMoney) {
            if (!flag) {
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            money -= takeMoney;
            System.out.println(Thread.currentThread().getName() + " 取了:" + takeMoney + " 余额:" + money);
            flag = false;
            this.notify();
        }
    }
    
    public class AddMoney implements Runnable{
        BankCard bankCard;
    
        public AddMoney() {
        }
    
        public AddMoney(BankCard bankCard) {
            this.bankCard = bankCard;
        }
    
        @Override
        public void run() {
            for(int i = 0; i < 10; i++) {
                bankCard.save(1000);
            }
        }
    }
    
    public class TakeMoney implements Runnable{
        BankCard bankCard;
    
        public TakeMoney() {
        }
    
        public TakeMoney(BankCard bankCard) {
            this.bankCard = bankCard;
        }
    
        @Override
        public void run() {
            for(int i = 0; i < 10; i++) {
                bankCard.take(1000);
            }
        }
    }
    
    public class BankTest {
        public static void main(String[] args) {
            BankCard bankCard = new BankCard();
            AddMoney addMoney = new AddMoney(bankCard);
            TakeMoney takeMoney = new TakeMoney(bankCard);
            Thread thread1 = new Thread(addMoney, "男");
            Thread thread2 = new Thread(takeMoney, "女");
            thread1.start();
            thread2.start();
        }
    }
    

    结果

    存取交替执行,没有问题

    男 存了:1000.0 余额:1000.0
    女 取了:1000.0 余额:0.0
    男 存了:1000.0 余额:1000.0
    女 取了:1000.0 余额:0.0
    ……
    

    2、将线程数量增加到 4 个,两个存钱,两个取钱

    public class BankTest {
        public static void main(String[] args) {
            BankCard bankCard = new BankCard();
            AddMoney addMoney = new AddMoney(bankCard);
            TakeMoney takeMoney = new TakeMoney(bankCard);
            Thread producerA = new Thread(addMoney, "生产者A");
            Thread producerB = new Thread(takeMoney, "生产者B");
            Thread customerA = new Thread(takeMoney, "消费者A");
            Thread customerB = new Thread(takeMoney, "消费者B");
            producerA.start();
            producerB.start();
            customerA.start();
            customerB.start();
        }
    }
    

    结果

    结果为乱序执行,而且最终形成死锁

    生产者A 存了:1000.0 余额:1000.0
    消费者A 取了:1000.0 余额:0.0
    生产者A 存了:1000.0 余额:1000.0
    生产者B 存了:1000.0 余额:2000.0
    ......
    

    原因

    • 生产者A抢到了CPU,存钱成功,修改标记为true,唤醒空,余额1000
    • 生产者B抢到了CPU,不能存,进入阻塞队列,释放锁和CPU
    • 生产者A抢到了CPU,不能存,进入阻塞队列,释放锁和CPU
    • 消费者A抢到了CPU,取钱成功,修改标记为false,唤醒生产者A,余额0
    • 生产者A抢到了CPU,存钱成功,修改标记为true,唤醒生产者B,余额1000
    • 生成者B抢到了CPU,存钱成功**(因为此时生产者B处于阻塞中,被唤醒并抢到CPU后不会再判断标记,是否可以存钱,而是直接执行接下来的代码)**,修改标记为true,唤醒空,余额2000

    解决

    将存钱和取钱的判断语句 if 修改为 while 后

    while (flag) {
        try {
            this.wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    

    结果

    生产者A 存了:1000.0 余额:1000.0
    消费者B 取了:1000.0 余额:0.0
    生产者A 存了:1000.0 余额:1000.0
    消费者B 取了:1000.0 余额:0.0
    ————————然后形成了死锁,程序卡在这里…
    

    原因

    生产者A抢到CPU,存钱成功,修改标记为true,唤醒空,(阻塞队列:)

    生产者B抢到CPU,不能存,进入阻塞队列……释放CPU和锁,(阻塞队列:生产者B)

    生产者A抢到CPU,不能存,进入阻塞队列……释放CPU和锁,(阻塞队列:生产者B、生产者A)

    消费者A抢到CPU,取钱成功,修改标记为false,唤醒生产者A,(阻塞队列:生产者B)

    消费者B抢到CPU,不能取,进入阻塞队列……释放CPU和锁,(阻塞队列:生产者B、消费者B)

    消费者A抢到CPU,不能取,进入阻塞队列……释放CPU和锁,(阻塞队列:生产者B、消费者B、消费者A)

    生产者A抢到CPU,存钱成功,修改标记为true,释放CPU和锁,唤醒生产者B(阻塞队列:消费者B、消费者A)

    生产者B抢到CPU,不能存,进入阻塞队列……释放CPU和锁,(阻塞队列:消费者B、消费者A、生产者B)

    生产者A抢到CPU,不能存,进入阻塞队列……释放CPU和锁,(阻塞队列:消费者B、消费者A、生产者B、生产者A)

    此时四个线程都进入了阻塞队列中,没有可以唤醒的线程了,所以就形成了死锁

    解决

    • 将两个方法中的 notify() 换成 notifyAll(),就可以解决问题了
    public synchronized void save(double addMoney) {
        while (flag) {
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        money += addMoney;
        System.out.println(Thread.currentThread().getName() + " 存了:" + addMoney + " 余额:" + money);
        flag = true;
        this.notifyAll();
    }
    
    • 因为这样每次会唤醒所有线程,所以不会存在唤醒一个不可执行的线程的情况

    结果

    生产者先存钱,然后消费者取钱,交替执行

    生产者A 存了:1000.0 余额:1000.0
    消费者B 取了:1000.0 余额:0.0
    生产者B 存了:1000.0 余额:1000.0
    消费者A 取了:1000.0 余额:0.0
    生产者B 存了:1000.0 余额:1000.0
    消费者B 取了:1000.0 余额:0.0
    ......
    

  • 您还可以看一下 汤小洋老师的跟汤老师学Java(第4季):选择结构课程中的 嵌套if结构小节, 巩固相关知识点

用switch语句判断字符z,根据z的不同,在case下作不同运算,就不会一下子加减乘除全显示出来,你这段代码,相当于完全没有用到z