Java8与游戏开发(三)-程序员宅基地

技术标签: 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);
		}
	}
}

 

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/lin451791119/article/details/81023240

智能推荐

word-break 与 word-wrap_word-break keep all不兼容-程序员宅基地

break-word会对过长的单词做词内断词处理,这样单词始终会在容器中,不会溢出容器break-all很暴力的一种处理方法,过长单词先断词处理,占满一行,然后再换行处理每次看到这两个css属性都是一种眼晕的感觉,今天就来总结一下。首先我们来来分别介绍一下这两个属性有哪些值:word-break:值描述break-all允许单词内换行keep-all&nb..._word-break keep all不兼容

音频重采样到双声道_音频重采样 与 双耳合成立体声 csdn-程序员宅基地

代码未经测试,只是偶尔看到,做个备份,ffmpeg也自带有转音频声道的extern "C" {#include #include #include }// 这里是PortAudio的头文件#include #include #include struct AudioContext { AVCodecContext* code_音频重采样 与 双耳合成立体声 csdn

X11,GTK,QT,GNOME的区别与联系_xorg clients与server失联-程序员宅基地

X11,GTK,QT,GNOME的区别与联系X11是X Window System Protocol, Version 11(RFC1013),是X server和Xclient之间的通信协议。X server是xfree86/xorg驱动下的显示设备鼠标键盘统称,Xclient通过X11协议和xfree86/xorg实现的Xserver通信,比如,告诉它画一个左上角坐标为(x_xorg clients与server失联

SQL SERVER INSERT、UPDATE 、DELETE、SELECT增、改、删、查-程序员宅基地

1、insert插入一条记录: 2、insert插入多条记录: 3、update指定条件更新记录: 4、delete指定条件删除记录:delete * from person where id=25、delete删除所有记录:delete from person6、select查询表中所有数据:select * from person7、select指定条件查询:select * from p

Python列表插入操作_Nobody_cache的博客-程序员宅基地

记录以下今天刷力扣发现的Python语法小知识:列表插入1. insert()函数a=[1,2,3]a.insert(1,[4,5])#第一个参数表示插入位置的索引,第二个参数为插入内容print(a)#[1, [4, 5], 2, 3]#insert 操作支持插入整数、列表等多种数据类型2. 列表切片a=[1,2,3]a[1:1]=[4,5]print(a)#[1, 4, 5, 2, 3]如果想在某个位置批量插入某些元素,可以直接把要插入的元素打包成一个可迭代对象使用list[_python列表插入

HDU2203 亲和串-程序员宅基地

本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作。本文作者:ljh2000作者博客:http://www.cnblogs.com/ljh2000-jump/转载请注明出处,侵权必究,保留最终解释权!Problem Description 人随着岁数的增长是越大越聪明还是越大越笨,这是一个值得全世界科...

随便推点

git 解决冲突 和提交代码-程序员宅基地

提交代码git add xxxxgit commit -m ""git push冲突解决git add xxx <如果这一步操作报错>git stashgit pullgit stash pop误提交代码git reset HEAD -- 将file退回到unstage区...

vs key-程序员宅基地

Visual Studio Professional 2015简体中文版(专业版)KEY:HMGNV-WCYXV-X7G9W-YCX63-B98R2Visual Studio Enterprise 2015简体中文版(企业版)KEY:HM6NR-QXX7C-DFW2Y-8B82K-WTYJV

数据结构与算法-链表练习题_int middle = (start +end )/2 ;if(start>=end)-程序员宅基地

leetcode的几道链表练习题:package com.freshbin.basics.linkedlist;/** * @author freshbin * @date 2020/5/2 14:54 */public class ListNode { int val; ListNode next; ListNode(int x) { ..._int middle = (start +end )/2 ;if(start>=end)

.Net Core建站(1):EF Core+CodeFirst数据库生成-程序员宅基地

工具准备:工具:VS2017环境:.Net Core 2.0 ,EF7这里因为刚学习,自己遇到的坑:Powershell2.0升级3.0问题,下载安装包安装完成后重新电脑就好了。https://www.microsoft.com/zh-CN/download/details.aspx?id=40855 1,我们需要的是建一个解决方案,一个类库项目,以及一个Web项目..._.net core建站

Count the string hdu 3336(kmp next数组运用)-程序员宅基地

It is well known that AekdyCoin is good at string problems as well as number theory problems. When given a string s, we can write down all the non-empty prefixes of this string. For example: s: "ab...

再识C语言(基础篇)_7-2 乔乔的交友标准 (10 分)c语言_乔乔家的龙龙的博客-程序员宅基地

**小小目录**传统艺能????过渡区????正片开始字符串????转义字符????传统艺能????小编是大一菜鸟不赘述,欢迎大佬指点江山(QQ:1319365055)此前博客点我!点我!请搜索博主 【知晓天空之蓝】或扫码进入!(https://blog.51cto.com)感谢支持!过渡区????现在是北京时间8:06,去操场小跑一下完了硬是被破防整感冒了,得亏上午一二节无课,卷完博客真的就要躺平咯。正片开始字符串????刚看到字符串时,我的第一印象就是一串字符,结果证明我是_7-2 乔乔的交友标准 (10 分)c语言