麻烦老师帮忙看一下为什么不会被唤醒?

麻烦老师帮忙看一下为什么不会被唤醒?

public class j41ThreadCommunication {
    public static void main(String[] args){
        Num num = new Num();
        Producer p = new Producer(num);
        Consumer c = new Consumer(num);
        Thread ta = new Thread(p, "ta");
        Thread tb = new Thread(c, "tb");
        ta.start();
        tb.start();
    }
    //wait()中断方法执行,使线程等待
    //notify()唤醒处于等待的某一个线程,使其结束等待,
    //notifyAll()唤醒所有处于等待的线程。
}
class Num{
    private int a = 0;
    boolean flag = false;
    public void setA(int a){
        this.a = a;
    }
    public int getA(){
        return a;
    }
    public boolean isFlag() {
        return flag;
    }

    public void setFlag(boolean flag) {
        this.flag = flag;
    }
}
class Producer implements Runnable{
    Num num;
    public Producer(Num num){
        this.num = num;
    }
    @Override
    public synchronized void run(){
        int i = 0;
        while(i < 20){
            System.out.println("s1"+num.isFlag());
            if (num.isFlag()){
                try {
                    System.out.println("1sg");
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
                int  a = num.getA();
                System.out.print("sa:"+a);
                num.setA(++a);
                i++;

                System.out.println("生产"+i+"a:"+num.getA());
                num.setFlag(true);
            System.out.println("s2"+num.isFlag());
            this.notifyAll();
            System.out.println("激活消费");

        }

    }
}
class Consumer implements Runnable{
    Num num;
    public Consumer(Num num){
        this.num = num;
    }
    @Override
    public synchronized void run(){
        int i = 0;
        while(i < 20){
            System.out.println("x1"+num.isFlag());
            if(!num.isFlag()){
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
                int  a = num.getA();
                System.out.print("xa:"+a);
                num.setA(--a);
                i++;

                System.out.println("消费"+i+"a:"+num.getA());
                num.setFlag(false);
            System.out.println("x2"+num.isFlag());
            this.notifyAll();
            System.out.println("激活生产");

        }
    }
}


正在回答 回答被采纳积分+1

登陆购买课程后可参与讨论,去登陆

5回答
吃吃吃鱼的猫 2019-07-21 17:36:28

同学你好,同学新贴出来的代码运行后没有问题哦~

原因是:在每个线程执行过程中,对num加锁。

相当于两个资源访问num,加锁后,不会出现冲突,所以是正确的哦~

如果我的回答解决了你的疑惑,请采纳。祝:学习愉快~

提问者 qq_AnAvenue_0 2019-07-21 15:40:54
public class j41ThreadCommunication {
    public static void main(String[] args){
        Num num = new Num();
        Producer p = new Producer(num);
        Consumer c = new Consumer(num);
        Thread ta = new Thread(p, "ta");
        Thread tb = new Thread(c, "tb");
        ta.start();
        tb.start();
    }
    
}
class Num{
    private int a = 0;
    boolean flag = false;
    public void setA(int a){
        this.a = a;
    }
    public int getA(){
        return a;
    }
    public boolean isFlag() {
        return flag;
    }

    public void setFlag(boolean flag) {
        this.flag = flag;
    }
}
class Producer implements Runnable{
    Num num;
    public Producer(Num num){
        this.num = num;
    }
    @Override
    public void run(){
        int i = 0;
        while(i < 20){
            System.out.println("s1"+num.isFlag());
            if (num.isFlag()){
                synchronized (num){
                    try {
                        System.out.println("1sg");
                        num.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

            }

                int  a = num.getA();
                System.out.print("sa:"+a);
                num.setA(++a);
                i++;

                System.out.println("生产"+i+"a:"+num.getA());
                num.setFlag(true);
                //System.out.println("s2"+num.isFlag());
                synchronized (num){
                    num.notifyAll();
                }
                System.out.println("激活消费");
            }




    }
}
class Consumer implements Runnable{
    Num num;
    public Consumer(Num num){
        this.num = num;
    }
    @Override
    public void run(){
        int i = 0;
        while(i < 20){
            System.out.println("x1"+num.isFlag());
            if(!num.isFlag()){
                synchronized (num){
                    try {
                        num.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

            }
                int  a = num.getA();
                System.out.print("xa:"+a);
                num.setA(--a);
                i++;

                System.out.println("消费"+i+"a:"+num.getA());
                num.setFlag(false);
                //System.out.println("x2"+num.isFlag());
                synchronized (num){
                    num.notifyAll();
                }

                System.out.println("激活生产");



        }
    }
}

该代码可得到正确结果

吃吃吃鱼的猫 2019-07-21 15:35:10

同学你好,建议同学贴出相关的完整代码,方便老师为同学解答问题~

如果我的回答解决了你的疑惑,请采纳。祝:学习愉快~

吃吃吃鱼的猫 2019-07-21 11:33:20

同学你好,

在一个线程的run方法中,是不能直接调用此线程的notifyAll唤醒所有线程的方法的。

如果我的回答解决了你的疑惑,请采纳。祝:学习愉快~

  • 提问者 qq_AnAvenue_0 #1
    现在就是wait和notifyAll我都加了synchronized (num)就可以得到正确结果了是为什么? synchronized (num){ try { num.wait(); } catch (InterruptedException e) { e.printStackTrace(); } }------- synchronized (num){ num.notifyAll(); }
    2019-07-21 11:39:01
  • 提问者 qq_AnAvenue_0 #2
    两个run方法的synchronized要删掉
    2019-07-21 11:57:16
好帮手慕阿莹 2019-07-20 19:15:49

同学你好,同学不应该在生产者和消费着中进行wait(),而是在Num中wait()并唤醒。

在生产者和消费着中,应只是去调用他们的Num对象的set和get方法,

应该把synchronized加在 Num中的set和get方法上。无论是生产还是消费,都应该在Num去做,而Producer和Consumer 只是模拟调用方法。是否可以去生产还是消费,应该由Num去把控。

所以,老师对同学的代码做了如下修改。

public class j41ThreadCommunication {
    public static void main(String[] args){
        Num num = new Num();
        Producer p = new Producer(num);
        Consumer c = new Consumer(num);
        Thread ta = new Thread(p, "ta");
        Thread tb = new Thread(c, "tb");
        ta.start();
        tb.start();
    }
    //wait()中断方法执行,使线程等待
    //notify()唤醒处于等待的某一个线程,使其结束等待,
    //notifyAll()唤醒所有处于等待的线程。
}
class Num{
    private int a = 0;
    boolean flag = false;
    public synchronized void setA(int a){
    	if(flag) {
    		try {
				wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
    	}
    	this.a=a;
    	System.out.println("生成a的值"+a);
        this.flag = true;
        this.notifyAll();
    }
    public synchronized int getA(){
    	if(!flag) {
    		try {
				wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
    		
    	}
    	System.out.println("消费a的值"+a);
    	flag =false;
    	 this.notifyAll();
        return a;
    }

  
}
class Producer implements Runnable{
    Num num;
    public Producer(Num num){
        this.num = num;
    }
    @Override
    public  void run(){
    	int i =0;
      while (true) {
    	 
    	  num.setA(i);
    	  i++;
    	  try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
 
    }
}
class Consumer implements Runnable{
    Num num;
    public Consumer(Num num){
        this.num = num;
    }
    @Override
    public  void run(){
    	  while (true) {
    		 
    			System.out.println(num.getA());
    			try {
    				Thread.sleep(1000);
    			} catch (InterruptedException e) {
    				// TODO Auto-generated catch block
    				e.printStackTrace();
    			}
    		}
    	 
    }
}

建议同学可以再回顾一下本节课程 呦。

如果我的回答解决了你的疑惑,请采纳!祝学习愉快!

  • 提问者 qq_AnAvenue_0 #1
    我知道课程里老师是放在num对象里面,我这里尝试了在外面弄,只是想问为什么我这样写另一个线程不会被唤醒
    2019-07-21 11:06:54
  • 提问者 qq_AnAvenue_0 #2
    现在就是wait和notify我都加了synchronized (num)就可以得到正确结果了是为什么? synchronized (num){ try { num.wait(); } catch (InterruptedException e) { e.printStackTrace(); } }
    2019-07-21 11:20:08
问题已解决,确定采纳
还有疑问,暂不采纳

恭喜解决一个难题,获得1积分~

来为老师/同学的回答评分吧

0 星
请稍等 ...
意见反馈 帮助中心 APP下载
官方微信

在线咨询

领取优惠

免费试听

领取大纲

扫描二维码,添加
你的专属老师