zoukankan      html  css  js  c++  java
  • Android应用开发提高系列(2)——《Practical Java 中文版》读书笔记(下)


    声明

      欢迎转载,但请保留文章原始出处:) 

        博客园:http://www.cnblogs.com

        农民伯伯: http://over140.cnblogs.com

    系列

      Android应用开发提高系列(1)——《Practical Java 中文版》读书笔记(上)

    正文

      注意:条目和用语可能与书籍有所出入,但尽量保持原样加一些自己的理解。
      一、性能

        1. 先把焦点放在设计、数据结构和算法身上

          备注:良好的设计、明智的选择数据结构和算法可能比高效代码更重要。

        2.  不要依赖编译器优化技术

        3.  理解运行时(runtime)代码优化

          备注:JIT将bytecode于运行时转换为本地二进制码,从而提高性能。因此编译后代码被执行次数越多,本机代码生成代价就很合算。

        4.  连接字符串使用StringBuffer要比String快,尤其是大量字符串拼接

        5.  将对象创建成本降至最小

          备注:复用既有对象,不要创建非必要的对象,只在需要的时候才创建它们。

        6.  将同步化(synchronization)降至最低

          备注:如果synchronized函数抛出异常,则在异常离开函数之前,锁会自动释放。如果整个函数都需要被同步化,为了产生体积较小且执行速度较快的代码,请优先使用函数修饰符,而不是在函数内使用synchronized代码块。

        7.  尽可能使用stack变量

          备注:如果在函数中频繁访问成员变量、静态变量,可以用本地(local)变量替代,最后操作完后再赋值给成员/静态变量。

        8.  尽可能的使用static、final和private函数

          备注:此类函数可以在编译期间被静态决议(statically resolved),而不需要动态议决(dynamic resolved)。(子类无法覆写)

        9.  类的成员变量、静态变量都有缺省值,务须重复初始化

          备注:记住,本地变量没有缺省值(例如函数内定义的变量)。

        10.  尽可能的使用基本数据类型

          备注:如int、short、char、boolean,使得代码更快更小。

        11.  不要使用枚举器(Enumeration)和迭代器(Iterator)来遍历Vector

          备注:使用for循环+get()

        12.  使用System.arraycopy()来复制数组

          备注:使用System.arraycopy()代替for循环,可以产生更快的代码。如:

            public void copyArray(int[] src, int[] dest) {
                int size = src.length;
                System.arraycopy(src, 0, dest, 0, size);
            }

          System.arraycopy()是以native method实现的,可以直接、高效的移动原始数组到目标数组,因此它执行速度更快。

        13.  优先使用数组,然后才考虑Vector和ArrayList,理由:

          a).  Vector的get()是同步的

          b).  ArrayList基本上就是一个非线程同步的Vector,比Vector要快

          c).  ArrayList和Vector添加元素或移除元素都需要重新整理数组。

          备注:不要仅仅因为手上有个数不定的数据需要存储,就毫无选择的使用Vector或ArrayList。可以考虑创建一个足够大的数组,通常这样可能会浪费内存,但性能上的收益可能超过内存方面的代价。

        14.  手工优化代码

          a).  剔除空白函数和无用代码

          b).  削减强度

            备注:以更高效的操作替换成本昂贵的操作。一个常见的优化手法是使用复式复制操作符(如+=、-=)。

          c).  合并常量

            备注:将变量声明为final,使得操作在编译器就进行。

          d).  删减相同的子表达式

            备注:可用一个临时变量代替重复的表达式。

          e).  展开循环

            备注:如循环次数少且已知循环次数,可展开去掉循环结构,直接访问数组元素。缺点是会产生更多代码。

          f).  简化代数

            备注:使用数学技巧来简化表达式。(例如从1+..+100的问题)

          g).  搬移循环内的不变式

            备注:循环内不变化的表达式可用移至循环外,不必重复计算表达式。

        15.  编译为本机代码

          备注:将程序的某部分编译为本机二进制代码,然后通过JNI访问。

      二、多线程

        1.  对于实例(instance)函数,同步机制锁定的是对象,而不是函数和代码块。

          备注:函数或代码块被声明为synchronized并非意味它在同一时刻只能有一个线程执行(同一对象不同线程调用会阻塞)。Java语言不允许将构造函数声明为synchronized。

        2.  同步实例函数和同步静态函数争取的是不同的locks。

          备注:两者均非多线程安全,可以使用实例变量进行同步控制,如(byte[] lock = new byte[0]),比其他任何对象都经济。

        3.  对于synchronized函数中可被修改的数据,应使之成为private,并根据需要提供访问函数。如果访问函数返回的是可变对象,那么可以先克隆该对象。

        4.  避免无谓的同步控制

          备注:过度的同步控制可能导致代码死锁或执行缓慢。再次提醒,当一个函数声明为synchronized,所获得的lock是隶属于调用此函数的那个对象。

        5.  访问共享变量时请使用synchronized或volatile

          备注:如果并发性很重要,而且不需要更新很多变量,则可以考虑使用volatile。一旦变量被声明为volatile,在每次访问它们时,它们就与主内存进行一致化。如果使用synchronized,只在取得lock和释放lock时候才一致化。

        6.  在单一操作(single operation)中锁定所有用到的对象

          备注:如果某个同步函数调用了某个非同步实例函数来修改对象,它是线程安全的。使用同步控制时,一定要对关键字synchronized所作所为牢记在心。它锁定的是对象而非函数或代码。

        7.  以固定而全局性的顺序取得多个locks(机制)以避免死锁。P/181~P/185

          备注:嵌入[锁定顺序]需要额外的一些工作、内存和执行时间。

        8.  优先使用notifyAll()而非notify()

          备注:notify()和notifyAll()用以唤醒处以等待状态的线程,waite()则让线程进入等待状态。notify()仅仅唤醒一个线程。

        9.  针对wait()和notifyAll()使用旋转锁(spin locks)

          备注:旋转锁模式(spin-lock pattern)简洁、廉价,而且能确保等待着某个条件变量的代码能循规蹈矩。

        10.  使用wait()和notifyAll()替代轮询(polling loops)

          备注:调用wait()时会释放同步对象锁,暂停(虚悬,suspend)此线程。被暂停的线程不会占用CPU时间,直到被唤醒。如:

                public void run()
                {
                    int data;
                    while(true){
                        synchronized (pipe) {
                            while((data = pipe.getDate()) == 0){
                                try{
                                    pipe.waite();
                                }
                                catch(InterruptedException e){}
                            }
                        }
                        
                        //Process Data
                    }
                }

        11.  不要对已锁定对象的对象引用重新赋值。

        12.  不要调用stop()和suspend()

          备注:stop()中止一个线程时,会释放线程持有的所有locks,有搅乱内部数据的风险;suspend()暂时悬挂起一个线程,但不会释放持有的locks,可能带来死锁的风险。两种都会引发不可预测的行为和不正确的行为。

          当线程的run()结束时,线程就中止了运行。可以用轮询+变量来控制,如下代码:

                private volatile boolean stop;
                
                public void stopThread()
                {
                    stop = true;
                }
        
                public void run()
                {
                    while(!stop){
                        //Process Data
                    }
                }

            注意:这里使用了关键字volatile,由于Java允许线程在其 私有专用内存 中保留主内存变量的副本(可以优化),线程1对线程2调用了stopThread(),但线程2可能不会及时察觉到stop主内存变量已变化,导致不能及时中止线程。

      三、类与接口

        1.  实现一个final类(immutable class 不可变类)时,请遵循下列规则:

          a). 声明所有数据为private

          b).  只提供取值函数(getter),不提供赋值函数(setter)

          c).  在构造函数中设置有实例数据

          d).  如果函数返回、接受引用final对象,请克隆这个对象。

          e).  区别浅层拷贝和深层拷贝应用场景。如拷贝Vector需要使用深层拷贝。

        2.  实现clone()时记得调用super.clone()

          备注:不管是浅层拷贝还是深层拷贝都需要调用super.clone()。

        3.  别只依赖finalize()清理内存以外的资源

          备注:finalize()函数只有在垃圾回收器释放对象占用的空间之前才会被调用,回收时可能并非所有符合回收条件的对象都被回收,也无法保证是否被调用、何时调用。实现finalize()方法时记得调用super.finalize()。

        4.  在构造函数内应避免调用非final函数,以免被覆写而改变初衷。

    结束

      书是从朋友那边借过来的,拿到手也有一段时间,磨磨唧唧好多天才看了几十页,而余下部分从上篇文章到这篇文章也不过才3-5天。发现以这种方式来看书也不错,一方面能加快速度,一方面由于要写文章更加认真细读,还能提炼把书读薄记录分享出来,实在是很适合我这样的 :)

  • 相关阅读:
    Do You See Me? Ethical Considerations of the Homeless
    ELDER HOMELESSNESS WHY IS THIS AN ISSUE?
    Endoflife support is lacking for homeless people
    html内联框架
    html字体
    html块 div span
    html列表
    html表格
    SQL Server管理员专用连接的使用   作为一名DBA,经常会处理一些比较棘手的服务无响应问题,鉴于事态的严重性,多数DBA可能直接用“重启”大法,以便尽快的恢复生产环境的正常运转,但是多数情况
    如何配置最大工作线程数 (SQL Server Management Studio)
  • 原文地址:https://www.cnblogs.com/over140/p/2312434.html
Copyright © 2011-2022 走看看