
正文
java代码优化的书 java代码优化方法有哪些
提示:扫一扫查出行【扫一扫了解最新限行尾号】
复制提示
北大青鸟java培训:程序员需要关注哪些代码优化?
对于程序员来说,软件编程开发代码质量能够直接反应出一个程序员能力的高低,下面IT培训就一起来了解一下,在代码质量优化方面,我们需要关注哪些问题。
1.吹毛求疵般地执行编码规范严格执行代码编写规范,可以使一个项目乃至一个公司的代码具有完全统一的风格,就像同一个人编写的一样,而且命名良好的变量,函数,类和注释,也无疑可以提高代码的可读性.具体落实到执行层面,可以参照Google的编码规范或者java官方的编码规范,网上可以找到,关键是要严格遵守,并且在codereview时,严格要求,没有按照规范的一定要指出并且要求修改.实际情况往往是虽然大家都知道优秀的代码规范是怎样的,但在具体写代码的过程中,却执行的差强人意,很多情况是认识上不够重视,觉得一个变量或者函数的命名成哪样关系不大,所以不够推敲,注释很多也都不写,codereview的时候大家也都事不关己心态,或者觉得没必要太抠细节,导致慢慢的整个codebase变得越来越差.所以这里还是要强调一下,细节决定成败,提高团队对代码规范的认同及其严格的执行是关键.2.编写高质量的单元测试单元测试是容易执行,且对提高代码质量见效快的方法之一还。
但还是有很多公司对单元测试重视不够,包括一些大的互联网公司,不写或者随便写写。
有些工程师觉得有测试团队就够了,再写单元测试就是浪费时间。
其实测试团队的测试和单元测试是在不同层面上的,测试团队的测试一般是黑盒测试,系统层面的集成测试,对于复杂系统来说,组合爆炸,a测试团队无法穷举所有的测试用例。
单元测试是代码层面的测试,一般是针对类的测试。
既然无法从系统的整体上保证100%符合我们的预期,那单元测试起码能保证我们代码在细粒度上运行符合预期。
有些工程师认为开发任务重没时间写。
这个还是没有足够重视单元测试,觉得是可有可无的部分,才会有这样的想法。
写好单元测试,节省很多解决线上bug的时间,开发时间反而更充足了。
还有很多工程师虽然在写单元测试,但只对正常流程做测试。
代码中的bug多数是写代码时异常情况没有考虑全面导致的,正常流程一般不会出问题。
单元测试的作用就在于测试各种异常情况下代码的运行是否符合预期,所以只对正常流程测试无法发挥单元测试真正的作用。
一般情况下,单元测试代码量要比要测试的代码多,一般是1-2倍的样子,写单元测试本身没有太多的技术挑战,主要看工程师逻辑是否缜密,能够考虑各种异常情况,写起来比较枯燥,所以写高质量的单元测试的一方面要靠工程师的耐心执行,另一方面要靠团队的严格要求。
当然这些都是建立在对单元测试重要性的认同之上。
相关问答
Q1: Java编程中的性能优化如何实现?
性能优化我觉得应该分两步走,第一步:寻找性能瓶颈,第二步:性能调优;
下面分别进行分析:
第一步:寻找性能瓶颈
通常性能瓶颈的表象是资源消耗过多、外部处理系统的性能不足;或者资源消耗不多,但是程序效应还是很慢;
资源主要消耗在cpu,文件io,网络io以及内存方面,当某一资源消耗过多会造成系统响应慢;
外部处理系统的性能不足主要是所调用其他系统提供的功能或数据库的响应速度不够,外部系统慢可能也是资源消耗过多导致,数据库响应慢可以对数据库进行调优;
资源消耗不多但仍然慢主要原因是程序代码运行效率不高,未充分使用资源或程序结构不合理;
1.1cpu消耗分析
可以通过相关命令比如top,pidstat,找出各个类型消耗cpu的占比,最常见的就是us和sy类型分别代表用户进程消耗和线程间切换消耗;如果us过高可以找到相关的线程ID然后分析代码;如果sy过高是不是启动了过多的线程导致线程切换过多;
1.2文件io消耗
要跟踪线程的文件IO消耗,可以通过pidstat来查找,可以查到每秒的读写kb数;找到读写kb数多个线程,然后结合jstack找到相关的java代码,然后分析;
1.3网络io消耗
可以通过sar来分析网络的消耗状况,但是不能具体到每个线程所消耗的网络IO,只能对线程dump,查找产生了大量网络io的线程;
1.4内存消耗
结合top或pidstat,以及jvm的内存分析工具来分析内存消耗;要区分是jvm外的物理内存还是jvmheap区内存;如果是jvm外的物理内存要分析程序中DirectByteBuffer,如果是jvmheap可以通过jvisualvm来分析;
1.5资源消耗不多但仍然慢
主要原因是:锁竞争激烈,未充分使用硬件资源,数据量增长
第二步:性能调优
2.1jvm调优
主要包括各个代的大小、GC策略等;代大小的设置:避免新生代大小设置过小,或者过大;避免Survivor区过小或过大;合理设置新生代存活周期;GC策略根据吞吐量优先还是延迟优先进行设置策略;
2.2程序调优
1.CPU消耗严重解决
us过高主要是执行线程无任何挂起动作,可以进行Thread.sleep操作;sy过高主要是因为创建了过多的线程导致线程上下文切换;
2.文件IO消耗严重解决
造成文件IO消耗严重的原因主要是多个线程写大量的数据到同一个文件,导致文件很快变的很大,从而写入速度越来越慢,并造成各线程激烈竞争争抢文件锁,常用的调优方法:异步写文件,批量读写,限流,限制文件大小;
3.网络IO消耗严重解决
主要原因是同时发送或者接受的包太多,解决办法就是限流;
4.内存消耗严重解决
解决:释放不必要的引用,使用对象缓存池,采用合理的缓存失效策略,合理使用softReference和WeakReference;
2.3资源消耗不多但仍然慢
主要原因是:锁竞争激烈,未充分使用硬件资源
Q2: 北大青鸟设计培训:如何写出优质Java代码的4个技巧?
如果现在要求对你写的Java代码进行优化,那你会怎么做呢?作者在本文介绍了可以提高系统性能以及代码可读性的四种方法,如果你对此感兴趣,就让java课程一起来看看吧。
我们平时的编程任务不外乎就是将相同的技术套件应用到不同的项目中去,对于大多数情况来说,这些技术都是可以满足目标的。
然而,有的项目可能需要用到一些特别的技术,因此工程师们得深入研究,去寻找那些最简单但最有效的方法。
在以前一篇文章中,我们讨论了必要时可以使用的四种特殊技术,这些特殊技术可以创建更好的Java软件;而本文我们将介绍一些有助于解决常见问题的通用设计策略和目标实现技术,即: 1.只做有目的性的优化 2.常量尽量使用枚举 3.重新定义类里面的equals()方法 4.尽量多使用多态性值得注意的是,本文中描述的技术并不是适用于所有情况。
另外这些技术应该什么时候使用以及在什么地方使用,都是需要使用者经过深思熟虑的。
1.只做有目的性的优化大型软件系统肯定非常关注性能问题。
虽然我们希望能够写出最高效的代码,但很多时候,如果想对代码进行优化,我们却无从下手。
最重要的是天下没有免费的午餐,因此为了降低代价,我们通常会通过类似于缓存、循环展开或预计算值这类技术去实现优化,这样反而增加了系统的复杂性,也降低了代码的可读性。
如果这种优化可以提高系统的性能,那么即使变得复杂,那也是值得的,但是做决定之前,必须首先知道这两条信息: 1.性能要求是什么 2.性能瓶颈在哪里首先我们需要清楚地知道性能要求是什么。
如果最终是在要求以内,并且最终用户也没有提出什么异议,那么就没有必要进行性能优化。
但是,当添加了新功能或者系统的数据量达到一定规模以后就必须进行优化了,否则可能会出现问题。
在这种情况下,不应该靠直觉,也不应该依靠检查。
因为即使是像MartinFowler这样有经验的开发人员也容易做一些错误的优化,正如在重构(第70页)一文中解释的那样:如果分析了足够多的程序以后,你会发现关于性能的有趣之处在于,大部分时间都浪费在了系统中的一小部分代码中里面。
如果对所有代码进行了同样的优化,那么最终结果就是浪费了90%的优化,因为优化过以后的代码运行得频率并不多。
因为没有目标而做的优化所耗费的时间,都是在浪费时间。
Q3: java并发常识
1.java并发编程是什么
1, 保证线程安全的三种方法: a, 不要跨线程访问共享变量b, 使共享变量是final类型的c, 将共享变量的操作加上同步 2, 一开始就将类设计成线程安全的, 比在后期重新修复它,更容易。
3, 编写多线程程序, 首先保证它是正确的, 其次再考虑性能。 4, 无状态或只读对象永远是线程安全的。
5, 不要将一个共享变量 *** 在多线程环境下(无同步或不可变性保护) 6, 多线程环境下的延迟加载需要同步的保护, 因为延迟加载会造成对象重复实例化 7, 对于volatile声明的数值类型变量进行运算, 往往是不安全的(volatile只能保证可见性,不能保证原子性)。 详见volatile原理与技巧中, 脏数据问题讨论。
8, 当一个线程请求获得它自己占有的锁时(同一把锁的嵌套使用), 我们称该锁为可重入锁。在jdk1。
5并发包中, 提供了可重入锁的java实现-ReentrantLock。 9, 每个共享变量,都应该由一个唯一确定的锁保护。
创建与变量相同数目的ReentrantLock, 使他们负责每个变量的线程安全。 10,虽然缩小同步块的范围, 可以提升系统性能。
但在保证原子性的情况下, 不可将原子操作分解成多个synchronized块。 11, 在没有同步的情况下, 编译器与处理器运行时的指令执行顺序可能完全出乎意料。
原因是, 编译器或处理器为了优化自身执行效率, 而对指令进行了的重排序(reordering)。 12, 当一个线程在没有同步的情况下读取变量, 它可能会得到一个过期值, 但是至少它可以看到那个线程在当时设定的一个真实数值。
而不是凭空而来的值。 这种安全保证, 称之为最低限的安全性(out-of-thin-air safety) 在开发并发应用程序时, 有时为了大幅度提高系统的吞吐量与性能, 会采用这种无保障的做法。
但是针对, 数值的运算, 仍旧是被否决的。 13, volatile变量,只能保证可见性, 无法保证原子性。
14, 某些耗时较长的网络操作或IO, 确保执行时, 不要占有锁。 15, 发布(publish)对象, 指的是使它能够被当前范围之外的代码所使用。
(引用传递)对象逸出(escape), 指的是一个对象在尚未准备好时将它发布。 原则: 为防止逸出, 对象必须要被完全构造完后, 才可以被发布(最好的解决方式是采用同步) this关键字引用对象逸出 例子: 在构造函数中, 开启线程, 并将自身对象this传入线程, 造成引用传递。
而此时, 构造函数尚未执行完, 就会发生对象逸出了。 16, 必要时, 使用ThreadLocal变量确保线程封闭性(封闭线程往往是比较安全的, 但一定程度上会造成性能损耗)封闭对象的例子在实际使用过程中, 比较常见, 例如 hibernate openSessionInView机制, jdbc的connection机制。
17, 单一不可变对象往往是线程安全的(复杂不可变对象需要保证其内部成员变量也是不可变的)良好的多线程编程习惯是: 将所有的域都声明为final, 除非它们是可变的。
2.Java线程并发协作是什么
线程发生死锁可能性很小,即使看似可能发生死锁的代码,在运行时发生死锁的可能性也是小之又小。
发生死锁的原因一般是两个对象的锁相互等待造成的。 在《Java线程:线程的同步与锁》一文中,简述死锁的概念与简单例子,但是所给的例子是不完整的,这里给出一个完整的例子。
/** * Java线程:并发协作-死锁 * * @author Administrator 2009-11-4 22:06:13 */ public class Test { public static void main(String[] args) { DeadlockRisk dead = new DeadlockRisk(); MyThread t1 = new MyThread(dead, 1, 2); MyThread t2 = new MyThread(dead, 3, 4); MyThread t3 = new MyThread(dead, 5, 6); MyThread t4 = new MyThread(dead, 7, 8); t1。 start(); t2。
start(); t3。start(); t4。
start(); } } class MyThread extends Thread { private DeadlockRisk dead; private int a, b; MyThread(DeadlockRisk dead, int a, int b) { this。 dead = dead; this。
a = a; this。b = b; } @Override public void run() { dead。
read(); dead。write(a, b); } } class DeadlockRisk { private static class Resource { public int value; }。
3.如何学习Java高并发
1.学习 *** 并发框架的使用,如ConcurrentHashMAP,CopyOnWriteArrayList/Set等2.几种并发锁的使用以及线程同步与互斥,如ReentainLock,synchronized,Lock,CountDownLatch,Semaphore等3.线程池如Executors,ThreadPoolExecutor等4.Runable,Callable,RescureTask,Future,FutureTask等5.Fork-Join框架以上基本包含完了,如有缺漏请原谅。
4.并发编程的Java抽象有哪些呢
一、机器和OS级别抽象 (1)冯诺伊曼模型 经典的顺序化计算模型,貌似可以保证顺序化一致性,但是没有哪个现代的多处理架构会提供顺序一致性,冯氏模型只是现代多处理器行为的模糊近似。
这个计算模型,指令或者命令列表改变内存变量直接契合命令编程泛型,它以显式的算法为中心,这和声明式编程泛型有区别。 就并发编程来说,会显著的引入时间概念和状态依赖 所以所谓的函数式编程可以解决其中的部分问题。
(2)进程和线程 进程抽象运行的程序,是操作系统资源分配的基本单位,是资源cpu,内存,IO的综合抽象。 线程是进程控制流的多重分支,它存在于进程里,是操作系统调度的基本单位,线程之间同步或者异步执行,共享进程的内存地址空间。
(3)并发与并行 并发,英文单词是concurrent,是指逻辑上同时发生,有人做过比喻,要完成吃完三个馒头的任务,一个人可以这个馒头咬一口,那个馒头咬一口,这样交替进行,最后吃完三个馒头,这就是并发,因为在三个馒头上同时发生了吃的行为,如果只是吃完一个接着吃另一个,这就不是并发了,是排队,三个馒头如果分给三个人吃,这样的任务完成形式叫并行,英文单词是parallel。 回到计算机概念,并发应该是单CPU时代或者单核时代的说法,这个时候CPU要同时完成多任务,只能用时间片轮转,在逻辑上同时发生,但在物理上是串行的。
现在大多数计算机都是多核或者多CPU,那么现在的多任务执行方式就是物理上并行的。 为了从物理上支持并发编程,CPU提供了相应的特殊指令,比如原子化的读改写,比较并交换。
(4)平台内存模型 在可共享内存的多处理器体系结构中,每个处理器都有它自己的缓存,并且周期性的与主存同步,为什么呢?因为处理器通过降低一致性来换取性能,这和CAP原理通过降低一致性来获取伸缩性有点类似,所以大量的数据在CPU的寄存器中被计算,另外CPU和编译器为了性能还会乱序执行,但是CPU会提供存储关卡指令来保证存储的同步,各种平台的内存模型或者同步指令可能不同,所以这里必须介入对内存模型的抽象,JMM就是其中之一。 二、编程模型抽象 (1)基于线程模型 (2)基于Actor模型 (3)基于STM软件事务内存 …… Java体系是一个基于线程模型的本质编程平台,所以我们主要讨论线程模型。
三、并发单元抽象 大多数并发应用程序都是围绕执行任务进行管理的,任务是抽象,离散的工作单元,所以编写并发程序,首要工作就是提取和分解并行任务。 一旦任务被抽象出来,他们就可以交给并发编程平台去执行,同时在任务抽象还有另一个重要抽象,那就是生命周期,一个任务的开始,结束,返回结果,都是生命周期中重要的阶段。
那么编程平台必须提供有效安全的管理任务生命周期的API。 四、线程模型 线程模型是Java的本质模型,它无所不在,所以Java开发必须搞清楚底层线程调度细节,不搞清楚当然就会有struts1,struts2的原理搞不清楚的基本灾难(比如在struts2的action中塞入状态,把struts2的action配成单例)。
用线程来抽象并发编程,是比较低级别的抽象,所以难度就大一些,难度级别会根据我们的任务特点有以下几个类别 (1)任务非常独立,不共享,这是最理想的情况,编程压力为0。 (2)共享数据,压力开始增大,必须引入锁,Volatile变量,问题有活跃度和性能危险。
(3)状态依赖,压力再度增大,这时候我们基本上都是求助jdk 提供的同步工具。 五、任务执行 任务是一个抽象体,如果被抽象了出来,下一步就是交给编程平台去执行,在Java中,描述任务的一个基本接口是Runnable,可是这个抽象太有限了,它不能返回值和抛受检查异常,所以Jdk5。
0有另外一个高级抽象Callable。 任务的执行在Jdk中也是一个底级别的Thread,线程有好处,但是大量线程就有大大的坏处,所以如果任务量很多我们并不能就创建大量的线程去服务这些任务,那么Jdk5。
0在任务执行上做了抽象,将任务和任务执行隔离在接口背后,这样我们就可以引入比如线程池的技术来优化执行,优化线程的创建。 任务是有生命周期的,所以Jdk5。
0提供了Future这个对象来描述对象的生命周期,通过这个future可以取到任务的结果甚至取消任务。 六、锁 当然任务之间共享了数据,那么要保证数据的安全,必须提供一个锁机制来协调状态,锁让数据访问原子,但是引入了串行化,降低了并发度,锁是降低程序伸缩性的原罪,锁是引入上下文切换的主要原罪,锁是引入死锁,活锁,优先级倒置的绝对原罪,但是又不能没有锁,在Java中,锁是一个对象,锁提供原子和内存可见性,Volatile变量提供内存可见性不提供原子,原子变量提供可见性和原子,通过原子变量可以构建无锁算法和无锁数据结构,但是这需要高高手才可以办到。
5.Java高并发入门要怎么学习
1、如果不使用框架,纯原生Java编写,是需要了解Java并发编程的,主要就是学习Doug Lea开发的那个java.util.concurrent包下面的API;2、如果使用框架,那么我的理解,在代码层面确实不会需要太多的去关注并发问题,反而是由于高并发会给系统造成很大压力,要在缓存、数据库操作上要多加考虑。
3、但是即使是使用框架,在工作中还是会用到多线程,就拿常见的CRUD接口来说,比如一个非常耗时的save接口,有多耗时呢?我们假设整个save执行完要10分钟,所以,在save的时候,就需要采用异步的方式,也就是单独用一个线程去save,然后直接给前端返回200。
6.Java如何进行并发多连接socket编程呢
Java多个客户端同时连接服务端,在现实生活中用得比较多。
同时执行多项任务,第一想到的当然是多线程了。下面用多线程来实现并发多连接。
import java。。
*; import java。io。
*; public class ThreadServer extends Thread { private Socket client; public ThreadServer(Socket c) { this。 client=c; } public void run() { try { BufferedReader in=new BufferedReader(new InputStreamReader(client。
getInputStream())); PrintWriter out=new PrintWriter(client。 getOutputStream()); Mutil User but can't parallel while (true) { String str=in。
readLine(); System。out。
println(str); out。 println("has receive。
"); out。
flush(); if (str。equals("end")) break; } client。
close(); } catch (IOException ex) { } finally { } } public static void main(String[] args)throws IOException { ServerSocket server=new ServerSocket(8000); while (true) { transfer location change Single User or Multi User ThreadServer mu=new ThreadServer(server。 accept()); mu。
start(); } } }J。
7.如何掌握java多线程,高并发,大数据方面的技能
线程:同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器(PC),线程切换开销小。
(线程是cpu调度的最小单位)线程和进程一样分为五个阶段:创建、就绪、运行、阻塞、终止。多进程是指操作系统能同时运行多个任务(程序)。
多线程是指在同一程序中有多个顺序流在执行。在java中要想实现多线程,有两种手段,一种是继续Thread类,另外一种是实现Runable接口.(其实准确来讲,应该有三种,还有一种是实现Callable接口,并与Future、线程池结合使用。
8.java工程师需要掌握哪些知识
1.Core Java,就是Java基础、JDK的类库,很多童鞋都会说,JDK我懂,但是懂还不足够,知其然还要知其所以然,JDK的源代码写的非常好,要经常查看,对使用频繁的类,比如String, *** 类(List,Map,Set)等数据结构要知道它们的实现,不同的 *** 类有什么区别,然后才能知道在一个具体的场合下使用哪个 *** 类更适合、更高效,这些内容直接看源代码就OK了2.多线程并发编程,现在并发几乎是写服务端程序必须的技术,那对Java中的多线程就要有足够的熟悉,包括对象锁机制、synchronized关键字,concurrent包都要非常熟悉,这部分推荐你看看《Java并发编程实践》这本书,讲解的很详细3.I/O,Socket编程,首先要熟悉Java中Socket编程,以及I/O包,再深入下去就是Java NIO,再深入下去是操作系统底层的Socket实现,了解Windows和Linux中是怎么实现socket的4.JVM的一些知识,不需要熟悉,但是需要了解,这是Java的本质,可以说是Java的母体, 了解之后眼界会更宽阔,比如Java内存模型(会对理解Java锁、多线程有帮助)、字节码、JVM的模型、各种垃圾收集器以及选择、JVM的执行参数(优化JVM)等等,这些知识在《深入Java虚拟机》这本书中都有详尽的解释,或者去oracle网站上查看具体版本的JVM规范.5.一些常用的设计模式,比如单例、模板方法、代理、适配器等等,以及在Core Java和一些Java框架里的具体场景的实现,这个可能需要慢慢积累,先了解有哪些使用场景,见得多了,自己就自然而然会去用。
6.常用数据库(Oracle、MySQL等)、SQL语句以及一般的优化7.JavaWeb开发的框架,比如Spring、iBatis等框架,同样他们的原理才是最重要的,至少要知道他们的大致原理。8.其他一些有名的用的比较多的开源框架和包,ty网络框架,Apache mon的N多包,Google的Guava等等,也可以经常去Github上找一些代码看看。
暂时想到的就这么多吧,1-4条是Java基础,全部的这些知识没有一定的时间积累是很难搞懂的,但是了解了之后会对Java有个彻底的了解,5和6是需要学习的额外技术,7-8是都是基于1-4条的,正所谓万变不离其宗,前4条就是Java的灵魂所在,希望能对你有所帮助9.(补充)学会使用Git。如果你还在用SVN的话,赶紧投入Git的怀抱吧。
9.java 多线程的并发到底是什么意思
一、多线程1、操作系统有两个容易混淆的概念,进程和线程。
进程:一个计算机程序的运行实例,包含了需要执行的指令;有自己的独立地址空间,包含程序内容和数据;不同进程的地址空间是互相隔离的;进程拥有各种资源和状态信息,包括打开的文件、子进程和信号处理。线程:表示程序的执行流程,是CPU调度执行的基本单位;线程有自己的程序计数器、寄存器、堆栈和帧。
同一进程中的线程共用相同的地址空间,同时共享进进程锁拥有的内存和其他资源。2、Java标准库提供了进程和线程相关的API,进程主要包括表示进程的java.lang.Process类和创建进程的java.lang.ProcessBuilder类;表示线程的是java.lang.Thread类,在虚拟机启动之后,通常只有Java类的main方法这个普通线程运行,运行时可以创建和启动新的线程;还有一类守护线程(damon thread),守护线程在后台运行,提供程序运行时所需的服务。
当虚拟机中运行的所有线程都是守护线程时,虚拟机终止运行。3、线程间的可见性:一个线程对进程 *** 享的数据的修改,是否对另一个线程可见可见性问题:a、CPU采用时间片轮转等不同算法来对线程进行调度[java] view plaincopypublic class IdGenerator{ private int value = 0; public int getNext(){ return value++; } } 对于IdGenerator的getNext()方法,在多线程下不能保证返回值是不重复的:各个线程之间相互竞争CPU时间来获取运行机会,CPU切换可能发生在执行间隙。
以上代码getNext()的指令序列:CPU切换可能发生在7条指令之间,多个getNext的指令交织在一起。
Q4: 用java语言写一个判断一个整数是否为质数的程序(要求利用三种方法逐步优化实现)
我写了几种方法,并逐步优化,并且对每一种方法进行了1000000次的调用测试每种方法的速度,仅供参考:
import java.math.BigInteger;
public class Test_04 {
/**
* 最笨重的一种方法,用该整数分别除以比它小的数,看是否能被整除
*/
public boolean isPrimeNum_1(int num) {
// 识别小于2的数
if (num 2) {
return false;
}
for (int i = 2; i num; i++) {
if (num % i == 0) {
return false;
}
}
return true;
}
/**
* 优化第一种方法br
* 1、偶数不可能是质数br
* 2、对于大于2的数,如果一个数a大于数b的一半,那么b不可能被a整除
*/
public boolean isPrimeNum_2(int num) {
// 2特殊处理
if (num == 2) {
return true;
}
// 识别小于2的数和偶数
if (num 2 || num % 2 == 0) {
return false;
}
int max = num / 2;
for (int i = 3; i max; i += 2) {
if (num % i == 0) {
return false;
}
}
return true;
}
/**
* 在第二种方法上再次优化,利用数字的性质:br
* 一个数不是素数就是合数,那么一定可以由两个自然数相乘得到,其中一个大于或等于它的平方根,br
* 一个小于或等于它的平方根,并且成对出现。br
* 这样就可以把计算量大幅度减少
*/
public boolean isPrimeNum_3(int num) {
if (num == 2) {
return true;// 2特殊处理
}
if (num 2 || num % 2 == 0) {
return false;// 识别小于2的数和偶数
}
double sqrt = Math.sqrt(num);
for (int i = 3; i = sqrt; i += 2) {
if (num % i == 0) {
return false;
}
}
return true;
}
/**
* Java中的BigInteger中已经写好了一个判断是否为质数的方法,直接用就可以了
*/
public boolean isPrimeNum_4(int num) {
BigInteger integer = BigInteger.valueOf(num);
return integer.isProbablePrime(1);
}
public static void main(String[] args) {
Test_04 test_04 = new Test_04();
int num = 991;
System.out.println(test_04.isPrimeNum_1(num));
long startTime = System.currentTimeMillis();
for (int i = 0; i 1000000; i++) {
test_04.isPrimeNum_1(num);
}
long endTime = System.currentTimeMillis();
System.out.println("第一种方法运行时间:" + (endTime - startTime) + "ms");
System.out.println(test_04.isPrimeNum_2(num));
startTime = System.currentTimeMillis();
for (int i = 0; i 1000000; i++) {
test_04.isPrimeNum_2(num);
}
endTime = System.currentTimeMillis();
System.out.println("第二种方法运行时间:" + (endTime - startTime) + "ms");
System.out.println(test_04.isPrimeNum_3(num));
startTime = System.currentTimeMillis();
for (int i = 0; i 1000000; i++) {
test_04.isPrimeNum_3(num);
}
endTime = System.currentTimeMillis();
System.out.println("第三种方法运行时间:" + (endTime - startTime) + "ms");
System.out.println(test_04.isPrimeNum_4(num));
startTime = System.currentTimeMillis();
for (int i = 0; i 1000000; i++) {
test_04.isPrimeNum_4(num);
}
endTime = System.currentTimeMillis();
System.out.println("第四种方法运行时间:" + (endTime - startTime) + "ms");
}
}
输出结果:
true
第一种方法运行时间:2732ms
true
第二种方法运行时间:671ms
true
第三种方法运行时间:68ms
true
第四种方法运行时间:1064ms
关于java代码优化的书和java代码优化方法有哪些的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。








