怎么优化JAVA程序的执行效率和性能?
-
5 票
- 49
-
4 票
- 2441
可以参考下这个JAVA中优化代码性能都有哪些技巧?,我再补充点:
一、避免在循环条件中使用复杂表达式
在不做编译优化的情况下,在循环中,循环条件会被反复计算,如果不使用复杂表达式,而使循环条件值不变的话,程序将会运行的更快。例子:
- import java.util.Vector;
- class CEL {
- void method (Vector vector){
- for(int i =0; i < vector.size (); i++) // Violation
- ;// ...
- }
- }
更正:
- class CEL_fixed {
- void method (Vector vector){
- int size = vector.size ()
- for(int i =0; i < size; i++)
- ;// ...
- }
- }
二、为'Vectors' 和 'Hashtables'定义初始大小
JVM为Vector扩充大小的时候需要重新创建一个更大的数组,将原原先数组中的内容复制过来,最后,原先的数组再被回收。可见Vector容量的扩大是一个颇费时间的事。
通常,默认的10个元素大小是不够的。你最好能准确的估计你所需要的最佳大小。例子:
- import java.util.Vector;
- publicclass DIC {
- publicvoid addObjects (Object[] o){
- // if length > 10, Vector needs to expand
- for(int i =0; i< o.length;i++){
- v.add(o); // capacity before it can add more elements.
- }
- }
- publicVector v =newVector(); // no initialCapacity.
- }
更正:
自己设定初始大小。
- publicVector v =newVector(20);
- publicHashtable hash =newHashtable(10);
三、在finally块中关闭Stream
程序中使用到的资源应当被释放,以避免资源泄漏。这最好在finally块中去做。不管程序执行的结果如何,finally块总是会执行的,以确保资源的正确关闭。
四、使用'System.arraycopy ()'代替通过来循环复制数组,例子:
- publicclass IRB
- {
- void method (){
- int[] array1 =newint[100];
- for(int i =0; i < array1.length; i++){
- array1 [i]= i;
- }
- int[] array2 =newint[100];
- for(int i =0; i < array2.length; i++){
- array2 [i]= array1 [i]; // Violation
- }
- }
- }
更正:
- publicclass IRB
- {
- void method (){
- int[] array1 =newint[100];
- for(int i =0; i < array1.length; i++){
- array1 [i]= i;
- }
- int[] array2 =newint[100];
- System.arraycopy(array1,0, array2,0,100);
- }
- }
五、让访问实例内变量的getter/setter方法变成”final”
简单的getter/setter方法应该被置成final,这会告诉编译器,这个方法不会被重载,所以,可以变成”inlined”,例子:
- class MAF {
- publicvoid setSize (int size){
- _size = size;
- }
- privateint _size;
- }
更正:
- class DAF_fixed {
- finalpublicvoid setSize (int size){
- _size = size;
- }
- privateint _size;
- }
六、避免不需要的instanceof操作
如果左边的对象的静态类型等于右边的,instanceof表达式返回永远为true。
例子:
- publicclass UISO {
- public UISO (){}
- }
- classDogextends UISO {
- void method (Dog dog, UISO u){
- Dog d = dog;
- if(d instanceof UISO)// always true.
- System.out.println("Dog is a UISO");
- UISO uiso = u;
- if(uiso instanceofObject)// always true.
- System.out.println("uiso is an Object");
- }
- }
更正:
删掉不需要的instanceof操作。
- <coding-7lang="as">
- class Dog extends UISO {
- void method () {
- Dog d;
- System.out.println ("Dog is an UISO");
- System.out.println ("UISO is an UISO");
- }
- }
七、避免不需要的造型操作
所有的类都是直接或者间接继承自Object。同样,所有的子类也都隐含的“等于”其父类。那么,由子类造型至父类的操作就是不必要的了。例子:
- class UNC {
- String _id ="UNC";
- }
- classDogextends UNC {
- void method (){
- Dog dog =newDog();
- UNC animal =(UNC)dog; // not necessary.
- Object o =(Object)dog; // not necessary.
- }
- }
更正:
- classDogextends UNC {
- void method (){
- Dog dog =newDog();
- UNC animal = dog;
- Object o = dog;
- }
- }
八、对于常量字符串,用'String' 代替 'StringBuffer'
常量字符串并不需要动态改变长度。
例子:
- publicclass USC {
- String method (){
- StringBuffer s =newStringBuffer("Hello");
- String t = s +"World!";
- return t;
- }
- }
更正:
把StringBuffer换成String,如果确定这个String不会再变的话,这将会减少运行开销提高性能。
九、在字符串相加的时候,使用 ' ' 代替 " ",如果该字符串只有一个字符的话
例子:
- publicclass STR {
- publicvoid method(String s){
- Stringstring= s +"d" // violation.
- string="abc"+"d" // violation.
- }
- }
更正:
将一个字符的字符串替换成' '
- publicclass STR {
- publicvoid method(String s){
- Stringstring= s +'d'
- string="abc"+'d'
- }
- }
-
5 票
- 1529
尽量别用异常
异常对性能不利。抛出异常首先要创建一个新的对象。Throwable接口的构造函数调用名为fillInStackTrace()的本地(Native)方法,fillInStackTrace()方法检查堆栈,收集调用跟踪信息。只要有异常被抛出,VM就必须调整调用堆栈,因为在处理过程中创建了一个新的对象。 异常只能用于错误处理,不应该用来控制程序流程。
Try {} catch()要使用得当。
不要在循环中使用:
Try {
} catch() {
}
应把其放置在最外层。
尽量使用HashMap 和ArrayList ,除非必要,否则不推荐使用HashTable和Vector ,后者由于使用同步机制,而导致了性能的开销。
- 0"尽量别用异常": 实在不敢苟同啊, 至少说法太不严谨了. 用不用异常, 得看具体的程序逻辑吧, 该用的时候还是得用. 顶多说 不可以 滥用.
"循环中不要使用try{}catch(){}": 如果我的逻辑需要处理错误并 继续下一轮循环呢?
HashTable早就不推荐使用了, Java5 后同步map就应该用ConcurrentHashMap. – brayden 2013-05-06
-
3 票
- 1752
网站优化一般包含两方面的内容:“减小代码的体积”和“提高代码的运行效率”
一、不用new关键词创建类的实例用new关键词创建类的实例时,构造函数链中的所有构造函数都会被自动调用。但如果一个对象实现了Cloneable接口,我们可以调用它的clone()方法。clone()方法不会调用任何类构造函数。
在使用设计模式(DesignPattern)的场合,如果用Factory模式创建对象,则改用clone()方法创建新的对象实例非常简单。
二、使用非阻塞I/O版本较低的JDK不支持非阻塞I/OAPI。为避免I/O阻塞,一些应用采用了创建大量线程的办法(在较好的情况下,会使用一个缓冲池)。这种技术可以在许多必须支持并发I/O流的应用中见到,如Web服务器、报价和拍卖应用等。然而,创建Java线程需要相当可观的开销。JDK1.4引入了非阻塞的I/O库(java.nio)。如果应用要求使用版本较早的JDK,需要支持非阻塞I/O的软件包。
三、慎用异常异常对性能不利。抛出异常首先要创建一个新的对象。Throwable接口的构造函数调用名为fillInStackTrace()的本地(Native)方法,fillInStackTrace()方法检查堆栈,收集调用跟踪信息。只要有异常被抛出,VM就必须调整调用堆栈,因为在处理过程中创建了一个新的对象。异常只能用于错误处理,不应该用来控制程序流程。
四、不要重复初始化变量默认情况下,调用类的构造函数时,Java会把变量初始化成确定的值:所有的对象被设置成null,整数变量(byte、short、int、long)设置成0,float和double变量设置成0.0,逻辑值设置成false。当一个类从另一个类派生时,这一点尤其应该注意,因为用new关键词创建一个对象时,构造函数链中的所有构造函数都会被自动调用。
五、尽量指定类的final修饰符带有final修饰符的类是不可派生的。在Java核心API中,有许多应用final的例子,例如java.lang.String。为String类指定final防止了人们覆盖length()方法。另外,如果指定一个类为final,则该类所有的方法都是final。Java编译器会寻找机会内联(inline)所有的final方法(这和具体的编译器实现有关)。此举能够使性能平均提高50%。
六、尽量使用局部变量调用方法时传递的参数以及在调用中创建的临时变量都保存在栈(Stack)中,速度较快。其他变量,如静态变量、实例变量等,都在堆(Heap)中创建,速度较慢。另外,依赖于具体的编译器/JVM,局部变量还可能得到进一步优化。请参见《尽可能使用堆栈变量》。
七、乘法和除法修改后的代码不再做乘以的操作,而是改用等价的左移的操作,每左移1位相当于乘以2。相应地,右移1位操作相当于除以2。值得一提的是,虽然移位操作速度快,但可能使代码比较难于理解,所以最好加上一些注释。
-
0 票
- 87
我说说我的一些经验吧,呵呵,我还只是个菜鸟,供大家参考
1.如果程序中使用到循环的话,循环体中使用的对象最好在循环体外就定义好,避免重复定义
2.不要太依赖java的GC机制,在跳出变量的作用范围外,手动回收内存。将变量置为null
3.生成对象时,要分配给它合理的空间和大小
比如list,默认是size为10,当你程序中使用的空间大小大于10个时,尽量给它定义一个合适的初始化空间
4.对于程序中经常使用但是又不常变化的对象或者数据,可以使用缓存。但是也不要为了使用缓存
而用缓存
5.数据库查询时,只是查询需要的数据,最好不要
- select * from table ...
怎么优化JAVA程序的执行效率和性能?的更多相关文章
- 多余的Using Namespaces或引用会影响程序的执行效率么?
在.NET程序编写中,需要using相应命名空间或添加相应的References,可有时候没有使用到的命名空间也被添加到了Using Namespaces中,那么,这样会影响程序的执行效率么? 通过示 ...
- 多余的Using Namespaces或引用会影响程序的执行效率么?(转)
转自:http://www.cnblogs.com/Interkey/p/UsingNameSpace.html 多余的Using Namespaces或引用会影响程序的执行效率么? 在.NET程序编 ...
- [转帖]浅析java程序的执行过程
浅析java程序的执行过程 转帖来源: https://www.cnblogs.com/wangjiming/p/10315983.html 之前学习过 这一块东西 但是感觉理解的不深刻. copy一 ...
- 003 01 Android 零基础入门 01 Java基础语法 01 Java初识 03 Java程序的执行流程
003 01 Android 零基础入门 01 Java基础语法 01 Java初识 03 Java程序的执行流程 Java程序长啥样? 首先编写一个Java程序 记事本编写程序 打开记事本 1.wi ...
- Java程序的执行过程
Java程序的执行过程 编译器将 Java 源代码编译成字节码class文件 类加载到 JVM 里面后,执行引擎把字节码转为可执行代码 执行的过程,再把可执行代码转为机器码,由底层的操作系统完成执行
- 12个提高Java程序员工作效率的工具
Java开发者常常都会想办法如何更快地编写Java代码,让开发过程变得更加轻松,更加高效.目前,市面上涌现出越来越多的高效编程工具.团长总结了几个常用的工具,其中包含了大多数开发人员已经使用.正在使用 ...
- 一个Java程序的执行过程(转)
我们手工执行java程序是这样的: 1.在记事本中或者是UE的文本编辑器中,写好源程序: 2.使用javac命令把源程序编译成.class文件: 编译后的.class(类字节码)文件中会包含 ...
- 浅析java程序的执行过程
在研究任何一门语言时,无论是面向过程的c,c++(面向过程和面向对象),还是面向对象的.net,java等,弄清语言执行过程至关重要. 何为语言执行过程? 所谓语言执行过程,指对于任何一门语言,如j ...
- 检测Python程序的执行效率
无意中被问到代码执行效率的问题,那就总结一下检测代码执行效率的几种方式: 一.装饰器 在函数上加装饰器,来得到函数的执行时间. def cst_time(func, *args, **kwargs): ...
随机推荐
- TCP的分层结构
TFTP(Trivial File Transfer Protocol,简单文件传输协议)是TCP/IP协议族中的一个用来在客户机与服务器之间进行简单文件传输的协议,提供不复杂.开销不大的文件传输服务 ...
- 服务调用方案(Spring Http Invoker) - 我们到底能走多远系列(40)
我们到底能走多远系列(40) 扯淡: 判断是否加可以效力于这家公司,一个很好的判断是,接触下这公司工作几年的员工,了解下生活工作状态,这就是你几年后的状态,如果满意就可以考虑加入了. 主题: 场景: ...
- 跟开涛老师学shiro -- shiro简介
1.1 简介 Apache Shiro是Java的一个安全框架.目前,使用Apache Shiro的人越来越多,因为它相当简单,对比Spring Security,可能没有Spring Securi ...
- linux安装sqlcmd登录sqlserver
首先从微软网站下载sqlncli安装文件,link. 因为是在内网安装,首先手工下载unixODBC2.3.0.tar.gz,下载后上传到服务器. 将下载的tar文件文件,放在同build_dm.sh ...
- [转载] 已知strcpy的函数原型:char *strcpy(char *strDest, const char *strSrc),编写函数 strcpy(C++版)
已知strcpy的函数原型:char *strcpy(char *strDest, const char *strSrc)其中strDest 是目的字符串,strSrc 是源字符串.不调用C++/C ...
- leetcode 123. Best Time to Buy and Sell Stock III ----- java
Say you have an array for which the ith element is the price of a given stock on day i. Design an al ...
- Kernel panic - not syncing: Attempted to kill init
解决方法:系统启动的时候,按下‘e’键进入grub编辑界面,编辑grub菜单,选择“kernel /vmlinuz-2.6.23.1-42.fc8 ro root=/dev/vogroup00/log ...
- linux之pid文件
在命令行中经常看到*.pid文件 其实这些文件是在启动进程的时候系统给这个进程的master进程分配的进程号 比如/usr/local/nginx/logs/nginx.pid文件 打开这个文件会发现 ...
- Linux 下 Lua 与 LuaSQL 模块安装
相关说明: Lua最近在Nginx的web服务器上挺火的, 它的高效让更多开发喜欢上它, 本文讲述Lua与LuaSQL的安装. 在上几篇mysql-proxy的安装中有提到和操作过. 操作系统: Li ...
- CUDA编程
目录: 1.什么是CUDA 2.为什么要用到CUDA 3.CUDA环境搭建 4.第一个CUDA程序 5. CUDA编程 5.1. 基本概念 5.2. 线程层次结构 5.3. 存储器层次结构 5.4. ...