Java8与游戏开发(三)

游戏开发中,通常使用"n段式"代表道具和货币,也经常要把字符串转成Uniparam对象。

系统一定会频繁地生成UniParam对象,所以加入了WeakHashMap作为缓存,还对比了一下性能的差异。

/**
 * 统一变参参数配置格式
 * 
 * 定义ID : 参数1 & 参数2 & 参数3 & ...
 * 
 * 定义ID : [10,20] & [测试1,测试2] & 参数3 //表示值在 10,20中随机一个
 * 
 * 定义ID : [10~20] & [0.01~1.00]
 * //表示参数1在10到20中随机一个整数,参数2在0.01~1.00随机一个Double(最多小数点后两位)
 * 
 * 嵌套用{} 2003:1&{2003:1&2&3}&3
 * 
 * 
 * 约定,一般多个UniStrParam用分号(;)隔开 例如, 10056001;10056002;1:1.04&3&测试;2:333&509&测试
 * 
 *
 */
public class UniStrParamFaster {

	private List<String> arrayList;

	public List<String> getArrayList() {
		......
	}

	// 用于序列化
	public UniStrParamFaster() {
	}

	public UniStrParamFaster(String strUnit) {
		......
	}

	public int GetParamSize() {
		return arrayList.size() - 1;
	}

	public int GetDefineID() {
		......
	}

	public int GetIntParam(int index) {
		.......
	}

	public String GetStrParam(int index) {
		......
	}

	public double GetDoubleParam(int index) {
		.......
	}

	public UniStrParamFaster getUniStrParam(int index) {
		.......
	}

	/**
	 * 修改第pos个参数为value值
	 * 
	 * @param pos
	 * @param value
	 * @return
	 */
	public void modify(int pos, double value) {
		.......
	}

	/**
	 * 修改第pos个参数为value值
	 * 
	 * @param pos
	 * @param value
	 * @return
	 */
	public void modify(int pos, int value) {
		.......
	}

	/**
	 * 修改第pos个参数为value值
	 * 
	 * @param pos
	 * @param value
	 */
	public void modify(int pos, String value) {
		......
	}

	public String toString() {
		......
	}

	public String toUniString() {
		......
	}

//测试性能

	private static Map<String, UniStrParamFaster> weakCacheMap = new WeakHashMap<>();

	private static Map<String, UniStrParamFaster> lruCacheMap = new LruCacheMap<>();

	private static AtomicInteger factor = new AtomicInteger(0);

	public static String getTestStr() {
		StringBuilder str = new StringBuilder().append(factor.getAndIncrement())
				.append(":").append(factor.getAndIncrement())
				.append("&").append(factor.getAndIncrement())
				.append("&").append(factor.getAndIncrement());
		return str.toString();
	}

	public static UniStrParamFaster getParamFromWeakMap(String paramStr) {
		UniStrParamFaster paramData = weakCacheMap.get(paramStr);
		if (paramData == null) {
			paramData = new UniStrParamFaster(paramStr);
			weakCacheMap.put(paramStr, paramData);
		}
		return paramData;
	}

	public static UniStrParamFaster getParamFromLruMap(String paramStr) {
		UniStrParamFaster paramData = lruCacheMap.get(paramStr);
		if (paramData == null) {
			paramData = new UniStrParamFaster(paramStr);
			lruCacheMap.put(paramStr, paramData);
		}
		return paramData;
	}

	private final static ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());

	private static List<String> prepareData() {
		int a = 10000;
		int b = 1000;
		CountDownLatch countDownLatch = new CountDownLatch(a * b);
		List<String> data = Collections.synchronizedList(new ArrayList<>(800000));
		for (int i = 0; i < a; i++) {
			String d = getTestStr();
			executorService.execute(() -> {
				for (int j = 0; j < b; j++) {
					data.add(d);
					countDownLatch.countDown();
				}
			});
		}
		try {
			countDownLatch.await();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		Collections.shuffle(data);
		return data;
	}

	private static void test1() {
		List<String> data = prepareData();
		/Round1
		long startTime = System.currentTimeMillis();
		for (int i = 0; i < data.size(); i++) {
			final String d = data.get(i);
			new UniStrParamFaster(d);
		}
		System.out.println("new->" + (System.currentTimeMillis() - startTime));
		/Round2
		startTime = System.currentTimeMillis();
		for (int i = 0; i < data.size(); i++) {
			final String d = data.get(i);
			getParamFromWeakMap(d);
		}
		System.out.println("weakMap->" + (System.currentTimeMillis() - startTime));
		/Round3
		startTime = System.currentTimeMillis();
		for (int i = 0; i < data.size(); i++) {
			final String d = data.get(i);
			getParamFromLruMap(d);
		}
		System.out.println("lruCacheMap->" + (System.currentTimeMillis() - startTime));
		executorService.shutdown();
	}

	@SuppressWarnings("unused")
	private static void test2() {
		List<String> data = prepareData();
		long startTime = System.currentTimeMillis();
		for (int i = 0; i < data.size(); i++) {
			String d = data.get(i);
			getParamFromWeakMap(d);
		}
		System.out.println(System.currentTimeMillis() - startTime);
		System.gc();
		startTime = System.currentTimeMillis();
		for (int i = 0; i < data.size(); i++) {
			String d = data.get(i);
			getParamFromLruMap(d);
		}
		System.out.println(System.currentTimeMillis() - startTime);
	}

	@SuppressWarnings("unused")
	private static void test3() {
		List<String> data = prepareData();
		for (int i = 0; i < 31; i++) {
			if ((1 << i) > data.size()) {
				break;
			}
			LruCacheMap.setMAX_ENTRIES(1 << i);
			lruCacheMap.clear();
			long startTime = System.currentTimeMillis();
			for (int j = 0; j < data.size(); j++) {
				String d = data.get(j);
				getParamFromLruMap(d);
			}
			System.out.println("cache size:" + LruCacheMap.getMAX_ENTRIES() + "->" + (System.currentTimeMillis() - startTime));
		}
	}

	public static void main(String[] args) {
		test1();
		//test2();
		//test3();

	}
}

获取10000000次UniParam的结果如图:

image.png

LruCacheMap为什么这么快,因为使用了最近最少使用的策略,并且限制了元素的个数:

public class LruCacheMap<K, V> extends LinkedHashMap<K, V> {

	private static final long serialVersionUID = 6918023506928428613L;

	private static int MAX_ENTRIES = 10000;

	/**
	 * 获得允许存放的最大容量
	 * 
	 * @return int
	 */
	public static int getMAX_ENTRIES() {
		return MAX_ENTRIES;
	}

	/**
	 * 设置允许存放的最大容量
	 * 
	 * @param int max_entries
	 */
	public static void setMAX_ENTRIES(int max_entries) {
		MAX_ENTRIES = max_entries;
	}

	/**
	 * 如果Map的尺寸大于设定的最大长度,返回true,再新加入对象时删除最老的对象
	 * 
	 * @param Map.Entry eldest
	 * @return int
	 */
	protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
		return size() > MAX_ENTRIES;
	}

	public static void main(String[] args) {

		Map<Integer, Boolean> map = new LruCacheMap<Integer, Boolean>();
		LruCacheMap.setMAX_ENTRIES(10);
		System.out.println(map.size());
		for (int i = 0; i < 50; i++) {
			map.put(i, true);
			System.out.println(map.size());
			System.out.println(map);
		}
	}
}

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值