CSDNRGY 2024-06-16 18:50 采纳率: 85.2%
浏览 2
已结题

为什么此程序只有1个线程在执行?

为什么此程序只有1个线程在执行?
代码如下:

package demo;

public class AddSubDemo {

    public static void main(String[] args) {
        Resource resource = new Resource();
        new Thread(new AddRunnable(resource)).start();
        new Thread(new SubRunnable(resource)).start();
    }

}

class AddRunnable implements Runnable {

    private Resource resource;

    public AddRunnable(Resource resource) {
        this.resource = resource;
    }

    @Override
    public void run() {
        while (true) {
            try {
                resource.add();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }

}

class SubRunnable implements Runnable {

    private Resource resource;

    public SubRunnable(Resource resource) {
        this.resource = resource;
    }

    @Override
    public void run() {
        while (true) {
            try {
                resource.sub();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }

}

class Resource {
    private int num = 0;
    private boolean flag = true; // true:执行ADD;false:执行SUB

    public synchronized void add() throws InterruptedException {
        if (this.flag = false) {
            super.wait();
        }
        Thread.sleep(1000);
        this.num++;
        flag = false;
        System.out.println(Thread.currentThread().getName() + " " + this.num);
        super.notifyAll();
    }

    public synchronized void sub() throws InterruptedException {
        if (this.flag == true) {
            super.wait();
        }
        Thread.sleep(2000);
        this.num--;
        flag = true;
        System.out.println(Thread.currentThread().getName() + " " + this.num);
        super.notifyAll();
    }
}

日志如下:

Thread-01
Thread-02
Thread-03
Thread-04
Thread-05
Thread-06
Thread-07
  • 写回答

3条回答 默认 最新

  • 阿里嘎多学长 2024-06-16 18:51
    关注

    以下内容由CHATGPT及阿里嘎多学长共同生成、有用望采纳:


    从你提供的代码和日志来看,问题出在Resource类中的同步方法addsub上。这两个方法都使用了waitnotifyAll来控制线程的执行流程,但是存在一个逻辑错误,导致只有一个线程能够执行。

    问题在于add方法和sub方法中的条件判断:

    public synchronized void add() throws InterruptedException {
        if (this.flag = false) { // 这里应该是 ==
            super.wait();
        }
        // ...
    }
    
    public synchronized void sub() throws InterruptedException {
        if (this.flag == true) { // 这里条件是正确的
            super.wait();
        }
        // ...
    }
    

    在Java中,==是用于比较两个值是否相等的,而=是赋值操作符。在add方法中,if (this.flag = false)实际上是将false赋值给flag,而不是比较flag是否等于false。因此,这行代码将始终执行super.wait(),导致调用add方法的线程进入等待状态,并且不会唤醒。

    由于flag被错误地赋值为false,当sub方法执行时,if (this.flag == true)的条件判断为falsesub方法也会调用super.wait(),导致调用sub方法的线程也进入等待状态。

    由于两个线程都因为条件判断错误而进入等待状态,并且没有其他代码来唤醒它们,所以只有一个线程(在这个例子中是Thread-0)能够继续执行并打印日志。

    要解决这个问题,你需要将add方法中的条件判断改为比较操作符==,如下所示:

    public synchronized void add() throws InterruptedException {
        if (this.flag == false) { // 修正为比较操作符
            super.wait();
        }
        // ...
    }
    

    修正后,两个线程应该能够交替执行addsub方法,从而正确地更新num的值。同时,注意notifyAll()应该在条件满足后立即调用,以唤醒所有等待的线程,而不是在方法的最后。这样可以避免潜在的竞态条件。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论 编辑记录
查看更多回答(2条)

报告相同问题?

问题事件

  • 系统已结题 6月24日
  • 已采纳回答 6月16日
  • 创建了问题 6月16日

悬赏问题

  • ¥15 如何通过命令行操作统信360安全浏览器?
  • ¥15 upload-labs-master第三关
  • ¥15 关于LT3758反激式负压电源,功率三极管烧毁的问题
  • ¥20 aruba ap305 CAP转IAP
  • ¥20 rockchip rk3588 ffmedia运行异常
  • ¥30 如何用 Java 简单系统设计?(相关搜索:服务器|面向对象设计|随机数)
  • ¥15 鸿蒙开发(关键词-开发环境)
  • ¥15 错误使用 mex Embedding metadata in the MEX file failed.
  • ¥30 Fractal eXtreme 64-bit求解锁15天限制
  • ¥30 openvpn 启动错误