• 《码出高效》读书笔记


    面向对象

    接口

    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.操作数栈是什么?

  • 相关阅读:
    P1012拼数
    P1622释放囚犯
    P1064 金明的预算方案
    P1754球迷购票问题
    卡塔兰数
    P1474货币系统
    P2562kitty猫基因
    P3984高兴的津津
    5-servlet简介
    java通过百度AI开发平台提取身份证图片中的文字信息
  • 原文地址:https://www.cnblogs.com/expiator/p/11349407.html
Copyright © 2020-2023  润新知