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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
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去把控。

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
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下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号

在线咨询

领取优惠

免费试听

领取大纲

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