多线程无锁红包实现方案

多线程无锁红包实现方案

背景

代码

@Data
public class RedPacket {
          
   

    //红包总额
    private Double total;
    //红包份数
    private Integer counts;
    //红包分隔之后的载体
    private List<Double> values;
    //用来获取下标
    private AtomicInteger taskCounts;
    //红包公平概率
    private Double fairRate;

    private DecimalFormat decimalFormat =new DecimalFormat("#.00");

    public RedPacket(Double total, Integer counts,Double fairRate) {
          
   
        this.total = total;
        this.counts = counts;
        taskCounts = new AtomicInteger(counts);
        dealFairRate(fairRate);
        caculate(total,counts,this.fairRate);
    }

    private void dealFairRate(Double fairRate) {
          
   
        fairRate = fairRate<0?0:fairRate;
        fairRate = fairRate>1?1:fairRate;
        this.fairRate = fairRate;
    }

    public String get(){
          
   
        final int flag = taskCounts.getAndDecrement();
        if(flag>=0){
          
   
            return decimalFormat.format(values.get(flag));
        }else {
          
   
            return "手速慢了,该红包已经被抢空了";
        }
    }

    private void caculate(Double total, Integer counts,Double fairRate) {
          
   
        values = doubleMeanMethod(total,counts,fairRate);
    }
    public static double nextDouble(final double min,final double max){
          
   
        return min+((max-min)*new Random().nextDouble());
    }

    public static String format(double value){
          
   
        return new java.text.DecimalFormat("0.00").format(value);
    }

    public static List<Double> doubleMeanMethod(double money, int number,double fairRate){
          
   
        final ArrayList<Double> doubles = new ArrayList<>();
        if (money<=0&&number<1) {
          
   
            return null;
        }
        //一般频率均分,其余的随机。可以自己调整平分概率
        double avg = money*fairRate;
        money = money - avg;
        double avgP = avg/number;
        double amount,sum = 0;
        int remainNumber = number;
        //int i =1;
        while (remainNumber-->1){
          
   
            if(fairRate!=1.0){
          
   
                amount = nextDouble(0.01,money/remainNumber);
                //sum+=amount+avgP;
                //System.out.println("第" + i++ + "个人的领取的红包金额为:" + format(amount+avgP));
                money-=amount;
                doubles.add(amount+avgP);
            }else {
          
   
                doubles.add(avgP);
            }
        }
        doubles.add(money+avgP);
        //System.out.println("第" + i++ + "个人的领取的红包金额为:" + format(money+avgP));
        //sum+=money+avgP;
        //System.out.println("验证红包总金额为:" + format(sum));
        return doubles;
    }

    public static void main(String[] args) throws InterruptedException {
          
   
        final RedPacket redPacket = new RedPacket(100.00, 10,0.0);
        for (int i = 0; i <20 ; i++) {
          
   
            CompletableFuture.runAsync(()->{
          
   
                final String s = redPacket.get();
                System.out.println(s);
            });
        }
        Thread.sleep(10000);
        System.out.println("完成");
    }
}
经验分享 程序员 微信小程序 职场和发展