1. 程式人生 > >java多執行緒實現搶紅包

java多執行緒實現搶紅包

在準備寫這個程式碼之前,我著實的複習和加深了對執行緒操作的使用,同步和資料共享!

說一下程式碼的思路:

首先搶紅包,人、紅包抽象為兩個物件,人(獲取到紅包)紅包(總額,數量,提供生成隨機金額方法)

其中,生成隨機紅包有兩種方案,第一種:獲取的時候生成,第二種:先生成好所有的紅包

對於兩種方案都涉及到資料同步和共享,紅包的總額就是一個共享資料,獲取隨機生成的紅包金額方法需要加鎖,保證生成隨機金額時只有一個執行緒在操作。

坑的點: 1、如果錢數0.04,數量4個,類似這樣的需要特殊處理

 2、為了生成錢數的概率達到儘可能的平等 val = new Random().nextInt(totalVal/count);

 3、便於金額的操作,換算為整形進行操作

 4、隨機生成的金額可能是0,需要進行判斷處理

以下就是程式碼,如果有哪裡不對,請大佬指教!

package com.ccq;

import java.util.Random;

public class FirstThread {
	public static void main(String[] args) {
		// 10個紅包,5個人搶
		Bao bao = new Bao(10, 5);
		User user = new User(bao);
		for(int i=0;i<10;i++) {
			new Thread(user).start();
		}
	}
}

// 每一個使用者都是一個執行緒
class User implements Runnable{
	private Bao bao;
	public User(Bao bao) {
		this.bao = bao;
	}
	@Override
	public void run() {
		double money = bao.getRandomMoney();
		if(money == 0) {
			System.out.println(Thread.currentThread().getName() + "不好意思,您手慢了!");
		}else {
			System.out.println(Thread.currentThread().getName() + "搶到 " + money + "元");
		}
		
	}
}

class Bao{
	private double total; // 總錢數
	private int totalVal; // 隨機生成整數,將錢數化為整數
	private int count;	  // 紅包總數

	public Bao(double total, int count) {
		this.total = total;
		this.count = count;
		this.totalVal = (int)(total * 100);
	}
	
	public synchronized double getRandomMoney() {
		int val;
		// 當前剩餘錢數 0.04 4人
		if(count !=0 && totalVal / count == 1) {
			val = 1;
			totalVal = totalVal - val;
			count--;
			return val/100.0;
		}
		
		if(count <= 0) {
			val = 0;
		}else if(count == 1) {
			val = totalVal;
		}else {
			int temp; //剩下的金額
			while(true) {
				// 隨機生成當前金額的隨機數 [0,totalVal/count),儘量平均一點
				val = new Random().nextInt(totalVal/count);
				temp = totalVal - val;
				// 判斷生成的金額大於0,且剩餘的錢數夠剩下人平分到0.01元
				if(temp*1.0/(count-1) >= 1 && val > 0) {
					//System.out.println("生成金額 :" + val + "剩餘金額 :" + temp + "剩餘人數 :" + (count-1));
					break;
				}
			}
			totalVal = totalVal - val;
		}
		count--;
		return val/100.0;
	}
}

程式碼執行結果圖: