A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

今天在论坛里看见这么一个题,他发的代码是错的,帖子还是仅作者可见……自己做了半天也没做出来,线程间通讯有问题,我贴一下题目,和自己做的代码,求前辈高人给看一下
/**
* 模拟抢红包过程,生成5个红包(金额是随机生成的,范围在1-10元之间)
* 创建5个线程代表5个人,然后让这5个人去抢这5个红包,每次抢红包需要300ms的时间,
*  在控制台打印出 (xxx抢了xxx元)
* (不限定每人抢的次数并且抢到红包后还可以接着抢,每次生成一个红包)
*
*@author
*
*/

18 个回复

倒序浏览
本帖最后由 水月灬清影 于 2016-8-19 19:12 编辑

[Java] 纯文本查看 复制代码
//测试类
public class BonusDemo {
        public static void main(String[] args) {
                Bonus bon=new Bonus();
                SetThread st=new SetThread(bon);
                GetThread gt=new GetThread(bon);
                
                 Thread t0= new Thread(st);
         t0.setName("红包");
                 Thread t1 = new Thread(gt);
         t1.setName("1号");
         Thread t2 = new Thread(gt);
         t2.setName("2号");
         Thread t3 = new Thread(gt);
         t3.setName("3号");
         Thread t4 = new Thread(gt);
         t4.setName("4号");
         Thread t5 = new Thread(gt);
         t5.setName("5号");
        
         t0.start();
         t1.start();
         t2.start();
         t3.start();
         t4.start();
         t5.start();
        }
}


import java.util.Random;
//红包资源类
public class Bonus {
        private static int count=5;
        private static int bonus;
        private boolean flag;

        public synchronized void set(){
                if(this.flag==true){
                        try {
                                this.wait();
                        } catch (InterruptedException e) {
                               e.printStackTrace();
                        }
                }
                if(count>0){
                        Random r=new Random();
                        bonus=r.nextInt(10)+1;
                        count--;
                        System.out.println("红包已生成");
                        
                }
                this.flag=true;
                this.notify(); 
        }
        
        public synchronized void get(){
                if(this.flag==false){
                        try {
                                this.wait();
                        } catch (InterruptedException e) {
                        e.printStackTrace();
                        }
                }
                
                System.out.println(Thread.currentThread().getName()+bonus+"元");
                try {
                        Thread.sleep(300);
                } catch (InterruptedException e) {
                      e.printStackTrace();
                }
                
                this.flag=false;
                this.notify();
        }
}


public class SetThread implements Runnable {
        private static int count=5;
        private Bonus bon;
        public SetThread(Bonus bon) {
                this.bon=bon;
        }

        public void run() {
                while(count>0){
                        bon.set();
                        count--;
                }

        }

}


public class GetThread implements Runnable {
        private static int count=5;
        private Bonus bon;
        public GetThread(Bonus bon) {
                this.bon=bon;
        }
        public void run() {
                while(count>0){
                        count--;
                        bon.get();
                }
                
        }

}

回复 使用道具 举报
public class Test02 implements Runnable {

        Random ra = new Random();
        int i = 0;
        int[] arr = { ra.nextInt(10) + 1, ra.nextInt(10) + 1, ra.nextInt(10) + 1,
                        ra.nextInt(10) + 1, ra.nextInt(10) + 1 };
        Object obj = new Object();

        public void run() {
                while (true) {
                        synchronized (obj) {
                                if (i < 5) {
                                        try {
                                                Thread.sleep(300);
                                        } catch (InterruptedException e) {

                                                e.printStackTrace();
                                        }
                                        System.out.println(Thread.currentThread().getName() + "抢了"
                                                        + arr[i++] + "元");

                                } else {
                                        break;
                                }
                        }
                }
        }

}

测试
public class Test2 {
public static void main(String[] args) {
        Test02 t = new Test02();
        Thread p1 = new Thread(t,"小明");
        Thread p2 = new Thread(t,"小亮");
        Thread p3 = new Thread(t,"小强");
        Thread p4 = new Thread(t,"小红");
        Thread p5 = new Thread(t,"小花");
       
        p1.start();
        p2.start();
        p3.start();
        p4.start();
        p5.start();
       
}
}

回复 使用道具 举报
wyq0627java11 发表于 2016-8-19 19:34
public class Test02 implements Runnable {

        Random ra = new Random();

题目要求是抢一个,生成一个……
回复 使用道具 举报
我是来看楼主的答案的,好牛的样子,目前还没搞懂
回复 使用道具 举报
水月灬清影 发表于 2016-8-19 19:09
[mw_shl_code=java,true]
//测试类
public class BonusDemo {

你代码写得很好, 你把flag 判断语句的if 改成while 就可以了, 我还想问下你 你红包类的get 方法中
while(count>0){
      count--

}
回复 使用道具 举报
本帖最后由 lbx95272006 于 2016-8-25 01:24 编辑
水月灬清影 发表于 2016-8-19 19:09
[mw_shl_code=java,true]
//测试类
public class BonusDemo {

你代码写得很好, 你把flag 判断语句的if 改成while 就可以了, 我还想问下你 你抢红包类的get 方法中
while(count>0){
      count--
      b.get();
}
我试了下,count--放在方法前和放在方法后是有区别的,我想问下你,为什么会这样
回复 使用道具 举报
谢谢!但并不是if,while的问题,是单生产者多消费者的问题,我的代码如果注释掉线程2-5,实现单生产者单消费者是没问题的。count用于计数5次,你说的有区别是什么区别?该不是线程随机性的区别吧…………
回复 使用道具 举报
求解求解求解
回复 使用道具 举报
我试过了,把你的程序的if 改成 while 就可以了
回复 使用道具 举报
问题出在notify() 这个方法,我把你的notify()方法也改了下,改成notifyAll()  前面的方法每次只唤醒一个线程,如果唤醒的线程是同伴,那么同伴就会逃脱if标记的判断,所以会出现多人抢到同一个红包,改成while 就是为了重复判断if标记
回复 使用道具 举报
本帖最后由 水月灬清影 于 2016-8-25 12:55 编辑
lbx95272006 发表于 2016-8-25 11:46
问题出在notify() 这个方法,我把你的notify()方法也改了下,改成notifyAll()  前面的方法每次只唤醒一个线 ...

!!!我把 if 改成 while,notify 改成 notifyAll 确实是实现了一个红包只有一个人抢到,但是题目要求的是一个人抢到之后还可以再抢,还需要如何改进呢?
回复 使用道具 举报
本帖最后由 水月灬清影 于 2016-8-25 12:54 编辑

感谢 lbx95272006 的指点,把红包资源类的 if 改成 while,notify 改成 notifyAll 可以实现一人一个红包,但是不合题目要求,题目讲的是抢到之后可以再抢,不限次数,所以还需要改进,还有哪位朋友有高见,目前代码如下:

[Java] 纯文本查看 复制代码
import java.util.Random;


//红包资源类
public class Bonus {
        private static int count=5;
        private static int bonus;
        
        private boolean flag;
        
        

        public synchronized void set(){
                while(this.flag==true){
                        try {
                                this.wait();
                        } catch (InterruptedException e) {
                                e.printStackTrace();
                        }
                }
                if(count>0){
                        Random r=new Random();
                        bonus=r.nextInt(10)+1;
                        count--;
                        System.out.println("红包已生成");
                        
                        
                }
                
                
                this.flag=true;
                this.notifyAll();
                
        }
        
        public synchronized void get(){
                while(this.flag==false){
                        try {
                                this.wait();
                        } catch (InterruptedException e) {
                                e.printStackTrace();
                        }
                }
                
                System.out.println(Thread.currentThread().getName()+bonus+"元");
                try {
                        Thread.sleep(300);
                } catch (InterruptedException e) {
                        e.printStackTrace();
                }
                
                this.flag=false;
                this.notifyAll();
        }
}
回复 使用道具 举报
lbx95272006 发表于 2016-8-25 11:46
问题出在notify() 这个方法,我把你的notify()方法也改了下,改成notifyAll()  前面的方法每次只唤醒一个线 ...

另外我试了一下,只改notifyAll,不把 if 改成 while 也可以实现你的效果。
回复 使用道具 举报
题目把你的问题掩盖了,如果题目要求你每次发的红包都要不一样,那么,你的这个程序就会出问题了,因为出现两人同时抢到一样的红包,你可以说是刚好那么巧,两次随机数都一样
把if 改成while    再把 你收红的线程里面的count--放到最后,就可以了
回复 使用道具 举报
lbx95272006 发表于 2016-8-25 17:19
题目把你的问题掩盖了,如果题目要求你每次发的红包都要不一样,那么,你的这个程序就会出问题了,因为出现 ...

照你说的改过之后,抢完5个红包程序不能终止,而且我没明白跟count--在前在后有什么关系
回复 使用道具 举报
我也不知道这之间的区别是什么, 所以这是我之前想请教你的,因为我试了下,放前和放后,效果不一样,我也没有想明白是为什么
回复 使用道具 举报
lbx95272006 发表于 2016-8-25 17:49
我也不知道这之间的区别是什么, 所以这是我之前想请教你的,因为我试了下,放前和放后,效果不一样,我也 ...

嗯,等以后对多线程理解深入之后再回过头来看看吧
回复 使用道具 举报
学习学习!
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马