jdk1.7的新特性
jdk1.7的新特性:
1,switch中可以使用字串了,呵呵还好
String s = "test";
switch (s) {
case "test" :
System.out.println("test");
case "test1" :
System.out.println("test1");
break ;
default :
System.out.println("break");
break ;
}
2,"<>"这个玩意儿的运用List<String> tempList = new ArrayList<>(); 即泛型实例化类型自动推断。
3. 语法上支持集合,而不一定是数组
final List<Integer> piDigits = [ 1,2,3,4,5,8 ];
4. 新增一些取环境信息的工具方法
File System.getJavaIoTempDir() // IO临时文件夹
File System.getJavaHomeDir() // JRE的安装目录
File System.getUserHomeDir() // 当前用户目录
File System.getUserDir() // 启动java进程时所在的目录
.......
5. Boolean类型反转,空指针安全,参与位运算
Boolean Booleans.negate(Boolean booleanObj)
True => False , False => True, Null => Null
boolean Booleans.and(boolean[] array)
boolean Booleans.or(boolean[] array)
boolean Booleans.xor(boolean[] array)
boolean Booleans.and(Boolean[] array)
boolean Booleans.or(Boolean[] array)
boolean Booleans.xor(Boolean[] array)
6. 两个char间的equals
boolean Character.equalsIgnoreCase(char ch1, char ch2)
7,安全的加减乘除
int Math.safeToInt(long value)
int Math.safeNegate(int value)
long Math.safeSubtract(long value1, int value2)
long Math.safeSubtract(long value1, long value2)
int Math.safeMultiply(int value1, int value2)
long Math.safeMultiply(long value1, int value2)
long Math.safeMultiply(long value1, long value2)
long Math.safeNegate(long value)
int Math.safeAdd(int value1, int value2)
long Math.safeAdd(long value1, int value2)
long Math.safeAdd(long value1, long value2)
int Math.safeSubtract(int value1, int value2)
Java抽象类型接口和抽象类
|
在没有好好地研习面向对象设计的设计模式之前,我对Java接口和Java抽象类的认识还是很模糊,很不可理解。刚学Java语言时,就很难理解为什么要有接口这个概念。 虽说是可以实现所谓的多继承,可一个只有方法名,没有方法体的东西,我实现它又有什么用呢?我从它那什么也得不到,除了一些方法名,我直接在具体类里加入这些方法不就行了吗? 为什么一定要有抽象类这个概念?为什么就不能把这个父类写成一个具体的类,子类再继承它不就可以了吗?何必弄一个抽象类出来,还要弄一些没有方法体的抽象方法,弄得又象接口又象类的,让人捉摸不定。 当我开始学习java设计模式,真正走进面向对象设计的大门之后,我才发现,自己对面向对象设计的理解原来是那么的片面,那么的肤浅,根本就没有真正理解面向对象思想的精髓,在某一种程度上还受着面向过程的影响,以为弄出了一个个类,就算是面向对象了,而其实还是被过程所驱使着。我还是说说我现在对面向对象思想的理解吧,不一定正确全面,但我想应该还算是比以前略有进步吧,面向对象思想,我觉得最关键的就是抽象。 一个软件设计的好坏,我想很大程度上取决于它的整体架构,而这个整体架构其实就是你对整个宏观商业业务的抽象框架,当代表业务逻辑的高层抽象层结构合理时,你底层的具体实现需要考虑的就仅仅是一些算法和一些具体的业务实现了。当你需要再开发另一个相近的项目时,你以前的抽象层说不定还可以再次利用呢,面对对象的设计,复用的重点其实应该是抽象层的复用,而不是具体某一个代码块的复用,是不是一下子感觉自己对复用理解的高度又上升了一层? 说到了抽象,就不能不提到曾让我头痛的Java接口和Java抽象类了,这也是本文我想说的重点。既然面向对象设计的重点在于抽象,那Java接口和Java抽象类就有它存在的必然性了。 Java接口和Java抽象类代表的就是抽象类型,就是我们需要提出的抽象层的具体表现。OOP面向对象的编程,如果要提高程序的复用率,增加程序的可维护性,可扩展性,就必须是面向接口的编程,面向抽象的编程,正确地使用接口、抽象类这些太有用的抽象类型做为你结构层次上的顶层,Java接口和Java抽象类有太多相似的地方,又有太多特别的地方,究竟在什么地方,才是它们的最佳位置呢?把它们比较一下,你就可以发现了。 1、Java接口和Java抽象类最大的一个区别,就在于Java抽象类可以提供某些方法的部分实现,而Java接口不可以,这大概就是Java抽象类唯一的优点吧,但这个优点非常有用。 如果向一个抽象类里加入一个新的具体方法时,那么它所有的子类都一下子都得到了这个新方法,而Java接口做不到这一点,如果向一个Java接口里加入一个新方法,所有实现这个接口的类就无法成功通过编译了,因为你必须让每一个类都再实现这个方法才行,这显然是Java接口的缺点。 2、一个抽象类的实现只能由这个抽象类的子类给出,也就是说,这个实现处在抽象类所定义出的继承的等级结构中,而由于Java语言的单继承性,所以抽象类作为类型定义工具的效能大打折扣。 在这一点上,Java接口的优势就出来了,任何一个实现了一个Java接口所规定的方法的类都可以具有这个接口的类型,而一个类可以实现任意多个Java接口,从而这个类就有了多种类型。 3、从第2点不难看出,Java接口是定义混合类型的理想工具,混合类表明一个类不仅仅具有某个主类型的行为,而且具有其他的次要行为。 4、结合1、2点中抽象类和Java接口的各自优势,具精典的设计模式就出来了:声明类型的工作仍然由Java接口承担,但是同时给出一个Java抽象类,且实现了这个接口,而其他同属于这个抽象类型的具体类可以选择实现这个Java接口,也可以选择继承这个抽象类,也就是说在层次结构中,Java接口在最上面,然后紧跟着抽象类,哈,这下两个的最大优点都能发挥到极至了。这个模式就是“缺省适配模式”。 在Java语言API中用了这种模式,而且全都遵循一定的命名规范:Abstract+接口名,Java接口和Java抽象类的存在就是为了用于具体类的实现和继承的,如果你准备写一个具体类去继承另一个具体类的话,那你的设计就有很大问题了。Java抽象类就是为了继承而存在的,它的抽象方法就是为了强制子类必须去实现的。 使用Java接口和抽象Java类进行变量的类型声明、参数是类型声明、方法的返还类型说明,以及数据类型的转换等。而不要用具体Java类进行变量的类型声明、参数是类型声明、方法的返还类型说明,以及数据类型的转换等。 我想,如果你编的代码里面连一个接口和抽象类都没有的话,也许我可以说你根本没有用到任何设计模式,任何一个设计模式都是和抽象分不开的,而抽象与Java接口和抽象Java类又是分不开的。理解抽象,理解Java接口和抽象Java类,我想就应该是真正开始用面向对象的思想去分析问题,解决问题了吧。 文章转自无双的博客, 原文地址:http://seawavenews.javaeye.com/blog/312668 |
Java实现读取本机网卡Mac地址的方法
本方法主要用来限制系统在其他的机器上运行.其实原理简单的很.没有调用第三方插件.代码如下:
package com.users.util; import java.io.*; import java.util.*; import java.util.regex.*; public class NetID { String IPCONFIG_COMMAND_WIN = "ipconfig /all"; boolean realMac = true; String unique = ""; public static String getMacAddress() { NetID hwid = new NetID(); return hwid.getUnique().trim(); } private String getUnique() { String os = System.getProperty("os.name"); if (os.startsWith("Windows")) { return getUniqueWindows(); }else { return ""; } } private String getUniqueWindows() { String ipConfigResponse = null; try { ipConfigResponse = runConsoleCommand(IPCONFIG_COMMAND_WIN); } catch (IOException e) { e.printStackTrace(); } StringTokenizer tokenizer = new StringTokenizer(ipConfigResponse, "/n"); while (tokenizer.hasMoreTokens()) { String line = tokenizer.nextToken().trim(); int macAddressPosition = line.indexOf(":"); if (macAddressPosition <= 0) { continue; } String macAddressCandidate = line.substring(macAddressPosition + 1). trim(); if (isMacAddWin(macAddressCandidate)) { if (realMac == true) { generateUnique(macAddressCandidate); } else { realMac = true; } } } |
认识理解Java中native的方法
Java不是完美的,Java的不足除了体现在运行速度上要比传统的C++慢许多之外,Java无法直接访问到操作系统底层(如系统硬件等),为此Java使用native方法来扩展Java程序的功能。
可以将native方法比作Java程序同C程序的接口,其实现步骤:
1、在Java中声明native()方法,然后编译;
2、用javah产生一个.h文件;
3、写一个.cpp文件实现native导出方法,其中需要包含第二步产生的.h文件(注意其中又包含了JDK带的jni.h文件);
4、将第三步的.cpp文件编译成动态链接库文件;
5、在Java中用System.loadLibrary()方法加载第四步产生的动态链接库文件,这个native()方法就可以在Java中被访问了。
JAVA本地方法适用的情况
1.为了使用底层的主机平台的某个特性,而这个特性不能通过JAVA API访问
2.为了访问一个老的系统或者使用一个已有的库,而这个系统或这个库不是用JAVA编写的
3.为了加快程序的性能,而将一段时间敏感的代码作为本地方法实现。
首先写好JAVA文件
/* * Created on 2005-12-19 Author shaoqi */ package com.hode.hodeframework.modelupdate; public class CheckFile { public native void displayHelloWorld(); static { System.loadLibrary("test"); } public static void main(String[] args) { new CheckFile().displayHelloWorld(); } } |
然后根据写好的文件编译成CLASS文件
然后在classes或bin之类的class根目录下执行javah -jni com.hode.hodeframework.modelupdate.CheckFile,
就会在根目录下得到一个com_hode_hodeframework_modelupdate_CheckFile.h的文件
然后根据头文件的内容编写com_hode_hodeframework_modelupdate_CheckFile.c文件
#include "CheckFile.h" #include #include JNIEXPORT void JNICALL Java_com_hode_hodeframework_modelupdate_CheckFile_displayHelloWorld(JNIEnv *env, jobject obj) { printf("Hello world!/n"); return; } |
之后编译生成DLL文件如“test.dll”,名称与System.loadLibrary("test")中的名称一致
vc的编译方法:cl -I%java_home%/include -I%java_home%/include/win32 -LD com_hode_hodeframework_modelupdate_CheckFile.c -Fetest.dll
最后在运行时加参数-Djava.library.path=[dll存放的路径]
Java内存泄漏分析与解决方案
Java内存泄漏是每个Java程序员都会遇到的问题,程序在本地运行一切正常,可是布署到远端就会出现内存无限制的增长,最后系统瘫痪,那么如何最快最好的检测程序的稳定性,防止系统崩盘,作者用自已的亲身经历与各位网友分享解决这些问题的办法。
作为Internet最流行的编程语言之一,Java现正非常流行。我们的网络应用程序就主要采用Java语言开发,大体上分为客户端、服务器和数据库三个层次。在进入测试过程中,我们发现有一个程序模块系统内存和CPU资源消耗急剧增加,持续增长到出现java.lang.OutOfMemoryError为止。经过分析Java内存泄漏是破坏系统的主要因素。这里与大家分享我们在开发过程中遇到的Java内存泄漏的检测和处理解决过程.
一. Java是如何管理内存
为了判断Java中是否有内存泄露,我们首先必须了解Java是如何管理内存的。Java的内存管理就是对象的分配和释放问题。在Java中,内存的分配是由程序完成的,而内存的释放是由垃圾收集器(Garbage Collection,GC)完成的,程序员不需要通过调用函数来释放内存,但它只能回收无用并且不再被其它对象引用的那些对象所占用的空间。
Java的内存垃圾回收机制是从程序的主要运行对象开始检查引用链,当遍历一遍后发现没有被引用的孤立对象就作为垃圾回收。GC为了能够正确释放对象,必须监控每一个对象的运行状态,包括对象的申请、引用、被引用、赋值等,GC都需要进行监控。监视对象状态是为了更加准确地、及时地释放对象,而释放对象的根本原则就是该对象不再被引用。
在Java中,这些无用的对象都由GC负责回收,因此程序员不需要考虑这部分的内存泄露。虽然,我们有几个函数可以访问GC,例如运行GC的函数System.gc(),但是根据Java语言规范定义,该函数不保证JVM的垃圾收集器一定会执行。因为不同的JVM实现者可能使用不同的算法管理GC。通常GC的线程的优先级别较低。JVM调用GC的策略也有很多种,有的是内存使用到达一定程度时,GC才开始工作,也有定时执行的,有的是平缓执行GC,有的是中断式执行GC。但通常来说,我们不需要关心这些。
二. 什么是Java中的内存泄露
导致内存泄漏主要的原因是,先前申请了内存空间而忘记了释放。如果程序中存在对无用对象的引用,那么这些对象就会驻留内存,消耗内存,因为无法让垃圾回收器GC验证这些对象是否不再需要。如果存在对象的引用,这个对象就被定义为"有效的活动",同时不会被释放。要确定对象所占内存将被回收,我们就要务必确认该对象不再会被使用。典型的做法就是把对象数据成员设为null或者从集合中移除该对象。但当局部变量不需要时,不需明显的设为null,因为一个方法执行完毕时,这些引用会自动被清理。
在Java中,内存泄漏就是存在一些被分配的对象,这些对象有下面两个特点,首先,这些对象是有被引用的,即在有向树形图中,存在树枝通路可以与其相连;其次,这些对象是无用的,即程序以后不会再使用这些对象。如果对象满足这两个条件,这些对象就可以判定为Java中的内存泄漏,这些对象不会被GC所回收,然而它却占用内存。
这里引用一个常看到的例子,在下面的代码中,循环申请Object对象,并将所申请的对象放入一个Vector中,如果仅仅释放对象本身,但因为Vector仍然引用该对象,所以这个对象对GC来说是不可回收的。因此,如果对象加入到Vector后,还必须从Vector中删除,最简单的方法就是将Vector对象设置为null。
Vector v = new Vector(10);for (int i = 1; i < 100; i++)......{ Object o = new Object(); v.add(o); o = null;}//此时,所有的Object对象都没有被释放,因为变量v引用这些对象。
实际上这些对象已经是无用的,但还被引用,GC就无能为力了(事实上GC认为它还有用),这一点是导致内存泄漏最重要的原因。再引用另一个例子来说明Java的内存泄漏。假设有一个日志类Logger,其提供一个静态的log(String msg),任何其它类都可以调用Logger.Log(message)来将message的内容记录到系统的日志文件中。
Logger类有一个类型为HashMap的静态变量temp,每次在执行log(message)的时候,都首先将message的值写入temp中(以当前线程+当前时间为键),在退出之前再从temp中将以当前线程和当前时间为键的条目删除。注意,这里当前时间是不断变化的,所以log在退出之前执行删除条目的操作并不能删除执行之初写入的条目。这样,任何一个作为参数传给log的字符串最终由于被Logger的静态变量temp引用,而无法得到回收,这种对象保持就是我们所说的Java内存泄漏。总的来说,内存管理中的内存泄漏产生的主要原因:保留下来却永远不再使用的对象引用。
三. 几种典型的内存泄漏
我们知道了在Java中确实会存在内存泄漏,那么就让我们看一看几种典型的泄漏,并找出他们发生的原因和解决方法。
3.1 全局集合
在大型应用程序中存在各种各样的全局数据仓库是很普遍的,比如一个JNDI-tree或者一个session table。在这些情况下,必须注意管理储存库的大小。必须有某种机制从储存库中移除不再需要的数据。
通常有很多不同的解决形式,其中最常用的是一种周期运行的清除作业。这个作业会验证仓库中的数据然后清除一切不需要的数据。
另一种管理储存库的方法是使用反向链接(referrer)计数。然后集合负责统计集合中每个入口的反向链接的数目。这要求反向链接告诉集合何时会退出入口。当反向链接数目为零时,该元素就可以从集合中移除了。
3.2 缓存
缓存一种用来快速查找已经执行过的操作结果的数据结构。因此,如果一个操作执行需要比较多的资源并会多次被使用,通常做法是把常用的输入数据的操作结果进行缓存,以便在下次调用该操作时使用缓存的数据。缓存通常都是以动态方式实现的,如果缓存设置不正确而大量使用缓存的话则会出现内存溢出的后果,因此需要将所使用的内存容量与检索数据的速度加以平衡。
常用的解决途径是使用java.lang.ref.SoftReference类坚持将对象放入缓存。这个方法可以保证当虚拟机用完内存或者需要更多堆的时候,可以释放这些对象的引用。
3.3 类装载器
Java类装载器的使用为内存泄漏提供了许多可乘之机。一般来说类装载器都具有复杂结构,因为类装载器不仅仅是只与"常规"对象引用有关,同时也和对象内部的引用有关。比如数据变量,方法和各种类。这意味着只要存在对数据变量,方法,各种类和对象的类装载器,那么类装载器将驻留在JVM中。既然类装载器可以同很多的类关联,同时也可以和静态数据变量关联,那么相当多的内存就可能发生泄漏。
Java和ant在windows下的环境变量的配置方法
以下设置WinXP及以上用户,右键点击我的电脑->属性->高级->环境变量,设置即可。设置完成后需重新启动命令提示符才能生效。具体如下:
JAVA环境变量设置
Windows下JAVA用到的环境变量主要有3个,JAVA_HOME、CLASSPATH、PATH。
JAVA_HOME指向的是JDK的安装路径,如D:/Program Files/IBM/Java50,在这路径下你应该能够找到bin、lib等目录。
设置方法:
JAVA_HOME = D:/Program Files/IBM/JAVA50
PATH环境变量原来Windows里面就有,只要保留原来的PATH的内容,并在其中加上%JAVA_HOME%/bin (%JAVA_HOME%就是是引用上一步设定好的环境变量JAVA_HOME) 。
设置方法:
PATH = %JAVA_HOME%/bin;%PATH%
同样,%PATH%是引用以前你设置的PATH环境变量,你照抄以前的值就行了。
注意的是最前面的"./;",这个是告诉JDK,搜索CLASS时先查找当前目录的CLASS文件,至于CLASSPATH后面指定tools.jar这个具体文件,是由java语言的import机制和jar机制决定的。
设置方法:
CLASSPATH = ./;%JAVA_HOME%/lib/tools.jar;%JAVA_HOME%/lib/dt.jar;%JAVA_HOME%/jre/lib/rt.jar
ANT环境变量设置
Windows下ANT用到的环境变量主要有2个,ANT_HOME 、PATH。
设置ANT_HOME指向ant的安装目录。
设置方法:
ANT_HOME = D:/apache_ant_1.7.0
将%ANT_HOME%/bin; %ANT_HOME%/lib添加到环境变量的path中。
设置方法:
PATH = %ANT_HOME%/bin; %ANT_HOME%/lib
Java趣味编程:快速排序法
快速排序是对冒泡排序的一种本质改进。它的基本思想是通过一趟扫描后,使得排序序列的长度能大幅度地减少。在冒泡排序中,一次扫描只能确保最大数值的数移到正确位置,而待排序序列的长度可能只减少1。快速排序通过一趟扫描,就能确保某个数(以它为基准点吧) 的左边各数都比它小,右边各数都比它大。然后又用同样的方法处理它左右两边的数,直到基准点的左右只有一个元素为止。
java
1 void quickSort(int[] arr, int left, int right){ 2 int p = partition(arr, left, right); 3 quickSort(arr, left, p-1); 4 quickSort(arr, p+1, right); 5 } 6 //1: 7 int partition(int[] arr, int left, int right){ 8 int p = left/2 + right/2; 9 while(left < right){ 10 while(left < p && arr[left] <= arr[p]){ 11 left++; 12 } 13 while(right > p && arr[right] >= arr[p]){ 14 right--; 15 } 16 swap(arr[left], arr[right]); 17 } 18 return p; 19 } 20 21 /*2: compare首先从high位置向前搜索找到第一个小于compare值的索引,并置换(这时high索引位置上的值为compare值);然后从 low位置往后搜索找到第一个大于compare值的索引,并与high索引上的值置换(这时low索引位置上的值为compare值);重复这两步直到 low=high为止。*/ 22 int partition(int[] arr, int left, int right){ 23 compare = a[left]; 24 while(left < right){ 25 while(left=compare){ 26 right--; 27 } 28 swap(arr[left], arr[right]); 29 30 while(left 31 left++; 32 } 33 swap(arr[left], arr[right]); 34 } 35 return left; 36 } |
Java游戏开发现状分析和走向
这篇文章是基本上是基于我的论文开题报告,所以难免要打点官腔。因为我对手机游戏并不了解,所以本文关于java手机游戏的讨论会很少,而即使对于手机游戏以外的内容,我个人所能接触到的资源也是很有限的,讨论起来不免会有所偏颇,大家批判着看吧。
这些年由于Java技术的不断发展,Java程序的运行速度有了显着提升,同时硬件技术也在不断进步,从而使得java处理比较复杂的3d图形成为可能。 Lwjgl,Jogl,Java3D等技术的出现,使Java语言可以方便的利用现在的显卡日益强大的硬件加速能力。实际上目前已经有许多基于java的 2d和3d游戏,其中不乏大型多人在线游戏。
Wurm online一个多人在线网络游戏(06年的时候进入了收费运行阶段,不过你还是可以申请一个免费帐号进去看看):
[url]http://www.wurmonline.com/[/url]
2007年javaone上jmokeyengine演示视频:
[url]http://www.youtube.com/watch?v=ho_b18HRmGA&eurl=http%3A%2F%2Fwww%2Ejmonkeyengine%2Ecom%2F[/url]
一个比较老的视频2005GDC上java游戏演示视频:
[url]http://www.youtube.com/watch?v=Pc3LxBIVaBs&feature=related[/url]
上面这些只是Java游戏的一小部分。然而,即使还有其它很多基于Java的游戏,相对于整个游戏产业来说,Java游戏社区仍然非常小,以至于其力量在手机游戏之外的领域几乎可以被忽略不计。但是实际上Java作为一种游戏编程语言和平台,这些年还是取得了长足的发展,在后applet时代走着复兴之路。
当然,Java可以做游戏,并不意味着Java就适合做游戏,那么:
基于java对于一个游戏来说到底意味着什么?
1,Java是一门经过充分发展,已经十分成熟的语言。
Java语言称霸企业级应用这么多年,事实证明了它非常适合于开发大型软件。当Java的运行效率不再是问题的时候,Jjava语言严谨、高抽象、可读性强的优势就体现出来了。这对于规模越来越庞大的游戏软件来说,有着不小的诱惑。
2,Java作为平台,极大的方便了游戏脚本的使用
对于游戏开发来说,由于涉及到比较复杂的情况(有时候甚至是美学问题),开发过程很多时候是一个不断修改的过程,可以方便的修改游戏内容是十分关键的。对于很多游戏引擎来说,都有自己编写的脚本解释器,用来解释一些自定义的游戏脚本语言(一般为命令式脚本,比如moveplayer(int x,int y),playersmile()之类的东西),另一些则提供了例如lua和rubby等的脚本语言来访问游戏引擎。由于其虚拟机特性,java本身就可以用来编写游戏脚本,目前也有例如beanshell、groovy等脚本语言可以方便的无缝的和java语言进行交互,这些都极大的方便了java游戏编程。
3,跨平台?
跨平台,每当比较java与其他语言的时候,总是要谈到跨平台。但是在java游戏领域,write once ,run everywhere,听起来更像是一个冷笑话。这个笑话有多冷呢?(手机游戏我不熟悉,但是确实有人用“痛苦”来形容开发运行在不同手机上的 javame游戏)对于其他大多数java游戏来说,或者通过applet或者通过java web start来部署,这两种方式无一例外的都要用到浏览器。对于java web start来说,问题相对较小,程序员必须处理的问题主要是如何让非专业用户成功安装指定的jre版本的问题,虽然很麻烦,但是是可以解决的。对于applet来说,问题就变得复杂的多,很多问题只会在特定的操作系统配上特定的浏览器时才会出现,即使是同一品牌的浏览器,不同的浏览器版本也会出现不同的问题,同时这里还涉及到客户机默认是使用opengl pipeline还是directdraw pipeline的问题。而我们现在甚至还没有开始讨论当3d游戏需要使用底层图形api时的情况,无论是applet还是web start一旦在程序中使用了任何一种opengl的java绑定,客户机各不相同的显卡以及同一款显卡的不同驱动都会带来不同的问题,而这些问题是随着操作系统和浏览器的不同而不同的,操作系统数×浏览器数(web start不需要考虑浏览器)×显卡数×每款显卡平均的驱动版本数=噩梦。最后你不得不妥协于这样一个现实-----即使电脑在硬件上满足程序的要求,你也无法让你的程序运行在这些电脑中的每一台上,除非你的用户都是专业人士。
当然,其实现状并没有听起来那么糟糕,对于不使用java的大多数游戏来说,根本就只能运行在一个平台上,许多游戏对directx或者 opengl的版本有要求,更不要提那些运行在家用游戏机上的游戏了,跨平台是整个游戏业的大问题,java只是像其他人一样没有把这个问题彻底解决掉而已,但仍然比其它技术做得要好。不过,值得一提的是,在那些不直接使用硬件加速的网页小游戏上,java确实在稳定性和方便安装上输给了flash;在家用机方面,java是0,而微软的xna(c#)可以跨xbox360和vista。
4,网络
Java一向强于解决网络方面的问题,在这方面,java主要有两个优势,第一是基于applet和java web start的游戏非常容易更新,不会像其他游戏那样需要用户手动下载全新版本;第二是java在网络交互的api相对比较友好,而对于大型网络游戏来说,分布式系统非常重要,这正是jcp的巨头们喜欢的东西,可能由于这是一个卖硬件的好机会,sun下了不少功夫开发了project dark star来做网络游戏服务端,由于这个工程还没有到1.0,所以现在也很难说具体好用不好用。
5,速度
这个没什么可讨论的,基于java的游戏肯定会比写得很好的c++程序慢,当然写一个好的c++程序所花费的庞大的薪水也是java不能比的。
总体说完,就具体说说:
当前在java游戏方面主要有哪些可以使用的技术
1,Java3D
作为sun公司较早推出的一项3d技术,是一种高度封装的api,构建在opengl和direct3d之上,可以说是最有名的java的3d技术。由于种种原因(api设计,面向的用户不明确),java3d一直没有办法流行,不久前java3d的团队宣布暂停对java3d新功能的开发,转而为JavaFX开发3d 渲染引擎。同时sun的另一个项目 project wonderland宣布将其渲染引擎由Java3d转为JMonkeyEngine。令人唏嘘的是sun的java3d再次进入尘封状态,大量基于 java3d的程序和教程都面临一个非常尴尬的境地;令人高兴的是在这一领域终于有比sun做得更好的团队出现了。引用别人对此事的评价:Java3D is dead! Long live Java "3D"!
2, Lwjgl([url]http://new.lwjgl.org/index.php[/url])
全名为light weight java game library。作为一个非官方的对java游戏的全面解决方案,lwjgl将游戏图形(opengl)、音效(openal)、控制输入集合为一,以成为java界的directx(不是direct3d)而努力。其在图形方面采用了opengl的java绑定,其函数与c语言版的完全相同,所以对于习惯opengl编程的程序员来说比较友好。目前有大量的java游戏和游戏引擎是基于lwjgl的,它可以说是java游戏社区最广为被使用的函数库之一。
原文地址 http://win.chinaunix.net/bbs/archiver/tid-26482.html
Java实现的线程池、消息队列功能方法
ThreadPoolManager类:负责管理线程池,调用轮询的线程来访问字符串缓冲区的内容,维护缓冲区,当线程池溢出时抛出的Runnable任务被加入到字符缓冲区。
public class ThreadPoolManager { private static ThreadPoolManager tpm = new ThreadPoolManager(); // 线程池维护线程的最少数量 private final static int CORE_POOL_SIZE = 4; // 线程池维护线程的最大数量 private final static int MAX_POOL_SIZE = 10; // 线程池维护线程所允许的空闲时间 private final static int KEEP_ALIVE_TIME = 0; // 线程池所使用的缓冲队列大小 private final static int WORK_QUEUE_SIZE = 10; // 消息缓冲队列 Queue msgQueue = new LinkedList(); // 访问消息缓存的调度线程 final Runnable accessBufferThread = new Runnable() { public void run() { // 查看是否有待定请求,如果有,则创建一个新的AccessDBThread,并添加到线程池中 if( hasMoreAcquire() ) { String msg = ( String ) msgQueue.poll(); Runnable task = new AccessDBThread( msg ); threadPool.execute( task ); } } }; final RejectedExecutionHandler handler = new RejectedExecutionHandler() { public void rejectedExecution( Runnable r, ThreadPoolExecutor executor ) { System.out.println(((AccessDBThread )r).getMsg()+"消息放入队列中重新等待执行"); msgQueue.offer((( AccessDBThread ) r ).getMsg() ); } }; // 管理数据库访问的线程池 final ThreadPoolExecutor threadPool = new ThreadPoolExecutor( CORE_POOL_SIZE, MAX_POOL_SIZE, KEEP_ALIVE_TIME, TimeUnit.SECONDS, new ArrayBlockingQueue( WORK_QUEUE_SIZE ), this.handler ); // 调度线程池 final ScheduledExecutorService scheduler = Executors .newScheduledThreadPool( 1 ); final ScheduledFuture taskHandler = scheduler.scheduleAtFixedRate( accessBufferThread, 0, 1, TimeUnit.SECONDS ); public static ThreadPoolManager newInstance() { return tpm; } |
- 默认分类(20)
- J2EE(25)
- Java(56)
- PHP(55)
- SEO(10)
- 网页设计(20)
- 网站建设(37)
- 数据库(7)
- JavaScript(17)
- JQuery(6)
- MySQL(20)
- SQL Server(6)
- Access(1)
- Oracle(6)
- office(6)
- Dreamweaver(4)
- Photoshop(12)
- Flash(9)
- Fireworks(13)
- CSS(14)
- HTML(4)
- .NET(7)
- ASP(2)
- DB2(1)
- Ajax(2)
- Linux(12)
- Struts(7)
- Hibernate(8)
- Spring(2)
- Jsp(22)
- Asp(8)
- C#(3)
- C++(1)
- 网络安全(5)
- 软件工程(7)
- XML(1)
- English(2)
- 计算机等级考试(2)
- 计算机病毒(4)
- 个人日志(76)
- 互联网(15)
- ActionScript(10)
- Android(3)
- 数据结构与算法(1)
- 游戏策略(3)
- 美文翻译(2)
- 编程开发(19)
- 计算机应用(4)
- 计算机(10)
- Unity3d(6)
- 其他(1)
- egret(1)
