zoukankan      html  css  js  c++  java
  • 《码出高效》读书笔记

    面向对象

    接口

    1.接口方法默认public abstract。
    接口属性访问控制符默认public statistatic final。

    2.接口支持多重继承,抽象类只能单继承。

    3.接口可以继承接口。

    方法

    1.方法参数必须做校验。比如判空。

    2.构造方法不能被继承,不能被重写。

    3.getter和setter中不要添加业务逻辑。

    否则程序出了问题,非常难排查。

    如果变量是 boolean 类型,那么 getter 方法可以命名为 isXxx()。

    4.异步用于处理耗时操作,处理完毕还可以返回处理结果。

    5.在pojo中,属性变量最好设置成包装类,这样在调用时没有经过setter,直接getter会报错空指针,便于发现问题。

    public class User {
    private Integer age;
    private Boolean vip;
    //getter、setter..
    }

    如果age设置成int,当调用时没有先setter,直接getter,会得到默认值0,但是不会报错。

    6.构造方法不可以被继承。

    7.static代码块只运行一次。

    static

    0.静态方法如果使用可修改的对象,那在并发时会存在线程安全的问题。

    1.阿里巴巴java规范:SimpleDateFormat是线程不安全的,不要定义为static变量。如果定义为static变量,必须加锁。

    声明SimpleDateFormat的时候,如果使用的是static定义的,那么这个SimpleDateFormat就是一个共享变量,随之,SimpleDateFormat中的calendar也就可以被多个线程访问到,就会出现线程安全问题。

    2.静态代码块只运行一次,在第二次对象实例化时,不会运行。

    代码风格

    1.魔法值,也就是直接以具体的数值或字符出现在代码中,随处可见,不易管理。魔法值应该改成常量。

    2.方法控制在80行内。

    3.if else超过三层以上,使用卫语句或状态模式。

    4.在if判断中,过长的表达式直接改为一个布尔类型变量表示。

    异常

    1.受检异常(check)和非受检异常(uncheck)。还有运行时异常(RuntimException)

    2.Error属于严重错误,比如OOM,StackOverflowError。

    2.受检异常可以通过try和catch捕获。运行时异常是编程错误引起的,需要程序员自己处理。

    并发与多线程

    线程

    1.线程是CPU调度和分派的基本单位,为了更充分地利用CPU资源,一般都会使用多线程进行处理。

    2.线程可以拥有自己的操作栈,程序计数器,局部变量表等资源,它与同一进程内的其他线程共享该进程的所有资源。

    3线程的生命周期分为NEW(新建状态),RUNNABLLE(就绪状态),RUNNING(运行状态),BLOCKING(阻塞状态),DEAD(销毁状态)。

    线程安全

    保证高并发场景下的线程安全,可以从以下维度考量:

    1.数据单线程内可见。

    通过限制数据仅在单线程内可见,可以避免数据被其他线程篡改。最典型的就是线程局部产量,它存储在独立虚拟机栈的局部变量列表,与其他线程毫无瓜葛。ThreadLocal就是用这种方式保证线程安全的。

    2.只读对象。

    只读对象是线程安全的。一个对象想要拒绝任何写入,必须满足:final修饰,避免被继承;没有任何更新方法;返回值不能为可变对象。

    3.线程安全类。比如StringBuffer。

    4.同步与锁机制。

    线程安全的核心是“要么只读,要么加锁”。

    Lock

    Lock利用了volatile的可见性。

    ReentrantLock对于Lock接口的实现主要依赖了Sync,而Sync继承了AbstractQueuedSynchronizer(AQS),它是JUC包实现同步的基础工具。在AQS中,定义了一个volatile int state 变量作为共享资源,如果线程获取资源失败,则进入同步FIFO队列中等待,如果成功获取资源就执行临界区代码。执行完释放资源时,会通知同步队列中的等待线程来获取资源后出列执行。

    继承AQS后,可以使用acquire(),release()方法获取、释放permit。

    Synchronized

    Synchronized的底层是通过监视锁(monitor)实现的。监视锁是每个对象都有的隐藏字段。如果线程进入同步方法或代码块时,会获取该方法或代码块所属对象的monitor,进行加锁判断。

    如果monitor为0,表示线程可以持有代码,monitor加一。如果当前线程已经持有monitor,则monitor继续加一。

    volatile

    解决的是多线程共享变量的可见性问题。但不具备Synchronied的互斥性。
    也不具有原子性。

    进行非原子操作,不具备线程安全。

    volatile适合一写多读的并发场景。

    数据结构与算法

    1.ArrayList,HashMap这些集合在初始化时,如果要放入的数据量过大,最好指定初始容量,避免多次扩容。

    2.HashMap 在容量不够进行 resize 时由于高并发可能出现死链,导致 CPU 飙升 。HashMap扩容后死链是如何形成的?

    疑问:

    1.双重检查锁如何理解?

    2.操作数栈是什么?

  • 相关阅读:
    洛谷 P1194 飞扬的小鸟 题解
    洛谷 P1197 星球大战 题解
    洛谷 P1879 玉米田Corn Fields 题解
    洛谷 P2796 Facer的程序 题解
    洛谷 P2398 GCD SUM 题解
    洛谷 P2051 中国象棋 题解
    洛谷 P1472 奶牛家谱 Cow Pedigrees 题解
    洛谷 P1004 方格取数 题解
    洛谷 P2331 最大子矩阵 题解
    洛谷 P1073 最优贸易 题解
  • 原文地址:https://www.cnblogs.com/expiator/p/11349407.html
Copyright © 2011-2022 走看看