使用Java多线程简单模拟抢红包(单例、观察者)

使用到了单例模式和观察者模式,但是对于细节的处理没有做好,还是有许多bug需要处理,不能通过特别小的红包金额的拆分测试。

最难的还是拆分红包的算法的设计吧。

public class RedPacketSystem {
    private RedPacketSystem(){}
    ArrayList<User> users = new ArrayList<>();
    private static RedPacketSystem sigleSystem = new RedPacketSystem();
    Vector<Float> splitBox;
    /**
     * 红包算法
     */
    public void splitMoney(float money, int num){
        Vector<Float> redpacket = new Vector<>();//随机拆分后的红包
        DecimalFormat df = new DecimalFormat(".00");
        float baseMon = money/(num/2);//总钱数除以拆分个数的一半
        float balanceMon = money;
        if(money/num<0.01){
            System.err.println("红包太小,无法拆分");
            System.exit(0);
        }
        if (money/num<0.1){
            //如果给的钱平均拆分后,比1毛钱还小,别随机了(太浪费性能),红包平均分
            float average = Float.parseFloat(df.format(money/num));
            while (num>0){
                if (num==1){
                    float finalBalance = Float.parseFloat(df.format(balanceMon));
                    redpacket.add(finalBalance);
                    break;
                }else if(balanceMon - average>0){
                    redpacket.add(average);
                    balanceMon-=average;
                    num--;
                }
            }
        }
        while (num>0) {
            float randomMon = (float) (Math.random()*baseMon+0.01);//最低是0.01
            if (num==1){
                float finalBalance = Float.parseFloat(df.format(balanceMon));
                redpacket.add(finalBalance);
                break;
            }else if (balanceMon - randomMon > 0) {
                float decimal2 = Float.parseFloat(df.format(randomMon));
                redpacket.add(decimal2);
                balanceMon-=decimal2;
                num--;
            }
        }
        this.splitBox = redpacket;
    }

    public static RedPacketSystem getInstance(){
        return sigleSystem;
    }
    public void addUser(User u){
        this.users.add(u);
    }
    public void deleteUser(User u){
        this.users.remove(u);
    }
    //通知观察者
    public void notifyUser(){
        for (int i = 0;i<this.users.size();i++){
            User user = users.get(i);
            new Thread(user).start();
        }
    }
    public Vector<Float> getSplitBox() {
        return splitBox;
    }
}
public class User implements Runnable {
    private String name;
    private static RedPacketSystem system = RedPacketSystem.getInstance();
    public User(String name){
        this.name = name;
    }

    public void sendRedRacket(float money,int num){
        //Vector<Float> redpacket
        RedPacketSystem system = RedPacketSystem.getInstance();
        System.out.println(this.name+"发红包啦,发了"+money+"元,总共"+num+"个包");
        system.splitMoney(money, num);
        system.notifyUser();
    }

    /**
     * 抢红包:snatchRedPacket
     */
    public void snatchRedPacket(){
        Vector<Float> redPacket = system.getSplitBox();
        try {
            Float money = redPacket.get(0);
            redPacket.remove(0);
            System.out.println(this.name + "抢到了" + money + "元");
        } catch (ArrayIndexOutOfBoundsException e) {
            System.out.println("很遗憾,"+this.name+"没有抢到红包");
        }
    }
    @Override
    public void run() {
        this.snatchRedPacket();
    }
}
public class Test {
    public static void main(String[] args) {
        RedPacketSystem sys = RedPacketSystem.getInstance();
        User user1 = new User("小明");
        User user2 = new User("小红");
        User user3 = new User("小张");
        User user4 = new User("小李");
        User user5 = new User("小五");
        sys.addUser(user1);
        sys.addUser(user2);
        sys.addUser(user3);
        sys.addUser(user4);
        sys.addUser(user5);
        //user1.sendRedRacket(80,4);
        user2.sendRedRacket(10F,3);
    }
}

在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_43598138/article/details/105750220