Java游戏服维护过程中发现的一些细节

开发 后端
Java游戏服维护过程中的2个细节问题,异常导致线程中断以及自动拆装箱遇到容器类的一些问题,详细请看下文

1.异常导致线程中断:

游戏中启动定时器,用来检测地图上掉落的物品是否到时,到时后从物品列表中清除。运行时发现,系统运行一段时间后就出现掉落物品不消失的情况,检查游戏逻辑没有发现任何问题,当前定时器任务中连抛出异常的可能都没有。在测试环境中使用各种方法测试都无法重现问题。只好万分头痛的去查看1GB/Hour的生产服运行日志,结果惊奇的发现用于检测物品到时的定时器在某个时间神奇的消失了。查找定时器消失前的日志发现当前线程抛出了一个异常,异常抛出点还真的不是发现问题的定时器任务。

原因分析:

定时器timer里面其实有一个线程和一个timerTask数组,创建timer的时候启动线程,然后线程负责轮询每个timerTask是否到时,到时后执行task中定义的操作。那么问题最终归结为异常为什么会导致线程中断。

标准的线程写法是在run方法里面放置一个循环,在循环结束以后,线程退出。那么如果在循环中的抛出异常而没有捕获,那么在跳出到循环外面之后,线程当然不会再执行了。同样定时器中的线程如果停止了,定时器里的所有任务当然也不会再执行了。

2.当自动拆装箱遇到容器类

自动拆装箱的功能用起来很爽,各种基本数据类型和对应的封装对象之间可以随意转换。但是不能忽视这个过程是有消耗资源的。

下面的代码:

  1. Integer i = 1

在编译后是这种样子的:

  1. Integer i = Integer.valueOf(1); 

所以对同一个值多次拆装箱的时候***将数据缓存一下,一点点的性能优化也是优化。

为什么容器类不支持基本数据类型?

好像这是一个约定俗成的概念,从学习java开始就被告诉容器类不支持基本数据类型,从来没有想过为什么。想一想其实也很简单,基本数据类型是游离于java万事万物皆对象的思想

之外的,与Object没有继承关系,所以要想支持只能针对每一个基本数据类型都写一套容器类。他们是图省事,当然都写一套也没有必要。

开始说正题,看下面的代码:

  1. import java.util.HashMap;  
  2. import java.util.Map;  
  3.    
  4. public class HashMapTest {  
  5.     Map<Integer, String> map;  
  6.        
  7.     public static void main(String[] args)  
  8.     {  
  9.         HashMapTest test = new HashMapTest();  
  10.         test.map = new HashMap<Integer, String>();  
  11.         test.map.put(1"s");  
  12.         test.print((short1);  
  13.     }  
  14.        
  15.     public void print(short key)  
  16.     {  
  17.         String s = map.get(key);  
  18.         System.out.println(s);  
  19.     }  

这是根据真实的生产服bug抽取的问题代码,当然不会写得这么直接,要不然肯定到不了我这里了。按照我的理解hashMap的实现是根据对象的hashCode值进行快速定位并比较查找的,
只要hashCode相同就应该得到正确的结果。所以特意查了一下源码发现返回的hashcode应该是完全相同的,这时就困惑了,看来之前的理解是有问题的。开源的东西就是有这点好处,
发现问题可以查看源码寻根问底,看下面的代码:

  1. public V get(Object key) {  
  2.         if (key == null)  
  3.             return getForNullKey();  
  4.         int hash = hash(key.hashCode());  
  5.         for (Entry<K,V> e = table[indexFor(hash, table.length)];  
  6.              e != null;  
  7.              e = e.next) {  
  8.             Object k;  
  9.             if (e.hash == hash && ((k = e.key) == key || key.equals(k)))  
  10.                 return e.value;  
  11.         }  
  12.         return null;  
  13.     } 

Integer的equals方法:

  1. public boolean equals(Object obj) {  
  2.     if (obj instanceof Integer) {  
  3.         return value == ((Integer)obj).intValue();  
  4.     }  
  5.     return false;  
  6.     } 

还是有一个问题,为什么get方法里面的参数不用泛型呢,如果用了泛型不就不会出现这种问题了。

原文链接:http://www.cnblogs.com/waynell/archive/2012/05/05/2444232.html

【编辑推荐】

  1. Java调用SQL Server的存储过程详解
  2. Java简单的网络爬虫实现
  3. JavaMe开发:低级界面绘图之菜单
  4. JavaMe开发:低级界面绘图之点阵字
  5. Apache CXF实战之三:传输Java对象
责任编辑:林师授 来源: 张玮丽的博客
相关推荐

2010-05-11 19:01:11

Unix系统

2012-06-25 10:13:00

Java.NET

2009-10-28 10:38:16

IDC调查虚拟化

2019-05-07 10:28:27

2012-04-19 10:06:55

微软Windows 8 E

2020-07-29 08:03:26

Celery异步项目

2020-06-28 08:26:07

正则表达式编程

2021-11-15 15:43:28

Windows 11升级微软

2013-05-31 02:18:47

ASP.NET.Net

2018-08-01 15:40:13

猜画小歌模型数据

2009-12-01 16:54:20

ADSL路由器安装

2011-08-01 13:59:22

Oracle数据库命名空间

2011-06-01 16:50:21

JAVA

2013-05-08 09:14:35

网络维护网吧网管

2018-06-28 09:38:16

2015-06-18 10:50:42

OS X Mac

2013-08-20 13:40:04

独立游戏开发者移动应用PR经验移动应用营销推广

2009-07-09 13:16:54

Java Swing开

2009-06-22 15:36:00

如何学好java

2009-06-18 09:51:25

Java继承
点赞
收藏

51CTO技术栈公众号