黑马程序员技术交流社区

标题: 多线程模拟抢红包~~~个人代码和心得 [打印本页]

作者: kansyoukyou    时间: 2016-9-28 11:19
标题: 多线程模拟抢红包~~~个人代码和心得
逛论坛看到的题目,自己试着做了下,经历几种错误的方向终于完成了。这里和大家分享下。


题目———模拟抢红包过程,生成5个红包(金额是随机生成的,范围在1-10元之间)创建5个线程代表5个人,然后让这5个人去抢这5个红包
*        每次抢红包需要300ms的时间, 在控制台打印出 (xxx抢了xxx元)
*      (每次生成一个红包,不限定每人抢的次数并且抢到红包后还可以接着抢)


第一种可能最常见的思路
~~~~~~~一开始我看到这个题,心里设想的是对真实红包的模拟,建了一个红包类Bag,定义了5个int型成员变量,然后在空参构造中用Random类生成每个变量的金额。然后又定义了一个Person继承了thread类,想在run()方法中写入一个getBag()的方法。
          而从这里开始,就出现了困难。我把getBag()写到了红包类中,空参,随机返回5个中的一个成员变量。在重写Person中的run()方法时就遇到了困难,get对getBag()方法的调用需要Bag的实例对象,而在run()中创建会生成5个Bag对象,也就是25个红包,每个人各自抢5个。
         于是试着在Person类中定义静态的Bag类对象,但是无法解决抢了被抢掉的红包的被重复抢的情况。在Bag类中写死了成员变量,无法实现对Bag类成员的增删操作。
         失败~睡觉~酝酿灵感~~~





作者: kansyoukyou    时间: 2016-9-28 11:21
第二种思路-----
   这次,我算是顺着老师说的,提高代码的重用性,创建了代表单个红包的红包类Bag,成员变量 num,空参构造自动为其赋值。接下来,就是抢红包的人的线程实现了。
   开始的思路是,利用集合实现,Person类中定义静态Integer型集合--ArrayList<Integerr> bag=new ArrayList();
然后添加了{1,2,3,4,5}五个值。
   run()方法中,随机生成0~5之间的一个数,代表抢到的红包序号,并生成一个新的Bag类对象,然后用bag.remove(int index),实现已经抢到了红包从集合中去除,并且在run()方法中每次抢进行了集合元素个数是否大于0的判断。
可是,因为ArrayList索引会随着元素变化而变化,第一次碰巧成功,之后每次都会在抢到一两个后报错,索引越界异常。

作者: kansyoukyou    时间: 2016-9-28 11:26
最后,经过几次实验终于成功实现,先说一个心得-----很大的心得----对于我们初学者来说--------------
在多线程中,不管你是继承Thread还是实现Runnable接口
在重写run()方法,一定尽量去保证run()中代码执行的独立性,不能去想着调用其他类中的方法,朝着在方法体中实现自己所有的变量,方法完成对外在执行的模拟。

说的我自己都有点凌乱,欢迎大家指正。
作者: kansyoukyou    时间: 2016-9-28 11:27
附上代码--------
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;

/**
* @author KanYouKyou
*         2.模拟抢红包过程,生成5个红包(金额是随机生成的,范围在1-10元之间)创建5个线程代表5个人,然后让这5个人去抢这5个红包
*         每次抢红包需要300ms的时间, 在控制台打印出 (xxx抢了xxx元)
*         (每次生成一个红包,不限定每人抢的次数并且抢到红包后还可以接着抢,)(10分)
*/
public class Hongbao {
        // 红包类,人(具有抢红包的功能)
        public static void main(String[] args) {
      
                Person p1 = new Person("赵日天");
                Person p2 = new Person("叶良辰");
                Person p3 = new Person("冯佳");
                Person p4 = new Person("kyou");
                Person p5 = new Person(" 龙傲天");
                p1.start();
                p2.start();
                p3.start();
                p4.start();
                p5.start();
        }
}

class Person extends Thread {
        public static Integer[] son = { 1, 2, 3, 4, 5 };
        public static ArrayList<Integer> bag = new ArrayList<>(Arrays.asList(son));

        public Person(String name) {
                super(name);
        }

       
        public void run() {
                try {
                        Thread.sleep(300);
                        synchronized (getClass()) {
                                if (bag.size() > 0) {

                                        Collections.shuffle(bag);
                                        System.out.println(getName() + "抢到了"+bag.get(bag.size() - 1)+"号"+new Bag());
                                        ;
                                        bag.remove(bag.size() - 1);
                                }
                        }

                } catch (InterruptedException e) {

                        e.printStackTrace();
                }
        }
}
作者: kansyoukyou    时间: 2016-9-28 11:30
红包类,其中值得注意的一个是我重写了toString方法。
import java.util.Random;

public class Bag {
private int num;

public Bag() {
        Random r=new Random();
        this.num=r.nextInt(10);
       
}

public int getNum() {
        return num;
}

@Override
public String toString() {
        return "红包金额为" + num ;
}

}
作者: 不羁的码农    时间: 2016-9-28 11:31
学习了,谢谢大神分享
作者: 18001105207    时间: 2016-9-28 12:02
66666666666666
作者: 宝瓶子    时间: 2016-9-28 12:06
学而时习之不亦说乎




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2