Java核心技术36讲笔记

一共43讲,大约需要10h

开篇词 1讲

java基础 14讲

java进阶 16讲

java安全基础 2讲

java性能基础 3讲

java应用开发扩展 4讲

周末福利 2讲

结束语 1讲

 

开篇词 (1讲)

初级、中级 Java 工程师要求:扎实的java和计算机科学基础,掌握主流开源框架的使用

高级java工程师或技术专家:全面考察java IO/NIO,并发,虚拟机,要求掌握底层源码、分布式、安全、性能等能力

注重面试者的计算机科学基础和编程语言的理解深度

面试失败的原因:

1、知其然不知其所以然,开发了很多业务应用,却没思考各种技术选型背后的逻辑。

导致:1、成长潜力有限,2无法达到高质量的设计实现

2、知识碎片化,不成系统。知识无法形成网络,无法完整、清晰的描述自己所开发的系统,或者使用的技术。

导致:1、面向搜索的编程方式,无法高效解决复杂问题,缺乏设计复杂系统的能力

比如:有并发编程经验,但对并发类库掌握不扎实。

 

模块一 Java基础 (14讲)

java的两个显著特性:跨平台,垃圾收集
详细回答的话,分五部分
java语言基本特性,Java类库,java生态,java虚拟机,Java工具
 

 

 

 

不要用Exception捕获,不要生吞异常,不要直接打印而是要打印到日志

try-catch会影响JVM对代码进行优化,所以建议仅捕获必要的代码段。

每实例化一个Exception,都会对当时的栈进行快照,这是一个比较重的操作,如果频繁发生,性能问题不可忽略

 
不同的引用类型,主要体现的是对象不同的可达性状态和对垃圾收集的影响。
强引用:普通对象引用,GC一般不会动该对象
强可达:当有线程可以不通过引用访问该对象时。比如,我们创建一个新对象,创建它的线程对它就是强可达。
软引用:jvm认为内存不足时,才会去试图回收软引用对象
软可达:就是只能通过软引用才能访问到的对象状态
弱引用:构建没有特定约束的关系,试图获取对象时,如果对象还在,就用它,否则重新实例化
弱可达:只能通过弱引用访问到的状态
幻象引用:也叫虚引用,仅仅提供了一种确保对象被finalize以后,做某些事的机制。
幻象可达:没有强、软、弱引用关联,并且finalize过了,只有幻象引用指向这个对象的时候。

 

 利用软引用和弱引用,可以将访问到的对象重新指向强引用,人为的改变可达性状态。

在Java语言中,除了基本数据类型外,其他的都是指向各类对象的对象引用;Java中根据其生命周期的长短,将引用分为4类。

1 强引用

特点:我们平常典型编码Object obj = new Object()中的obj就是强引用。通过关键字new创建的对象所关联的引用就是强引用。 当JVM内存空间不足,JVM宁愿抛出OutOfMemoryError运行时错误(OOM),使程序异常终止,也不会靠随意回收具有强引用的“存活”对象来解决内存不足的问题。对于一个普通的对象,如果没有其他的引用关系,只要超过了引用的作用域或者显式地将相应(强)引用赋值为 null,就是可以被垃圾收集的了,具体回收时机还是要看垃圾收集策略。

2 软引用

特点:软引用通过SoftReference类实现。 软引用的生命周期比强引用短一些。只有当 JVM 认为内存不足时,才会去试图回收软引用指向的对象:即JVM 会确保在抛出 OutOfMemoryError 之前,清理软引用指向的对象。软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被垃圾回收器回收,Java虚拟机就会把这个软引用加入到与之关联的引用队列中。后续,我们可以调用ReferenceQueue的poll()方法来检查是否有它所关心的对象被回收。如果队列为空,将返回一个null,否则该方法返回队列中前面的一个Reference对象。

应用场景:软引用通常用来实现内存敏感的缓存。如果还有空闲内存,就可以暂时保留缓存,当内存不足时清理掉,这样就保证了使用缓存的同时,不会耗尽内存。

3 弱引用

弱引用通过WeakReference类实现。 弱引用的生命周期比软引用短。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。由于垃圾回收器是一个优先级很低的线程,因此不一定会很快回收弱引用的对象。弱引用可以和一个引用队列(ReferenceQueue)联合使用,如果弱引用所引用的对象被垃圾回收,Java虚拟机就会把这个弱引用加入到与之关联的引用队列中。

应用场景:弱应用同样可用于内存敏感的缓存。

4 虚引用

特点:虚引用也叫幻象引用,通过PhantomReference类来实现。无法通过虚引用访问对象的任何属性或函数。幻象引用仅仅是提供了一种确保对象被 finalize 以后,做某些事情的机制。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。虚引用必须和引用队列 (ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之关联的引用队列中。
ReferenceQueue queue = new ReferenceQueue ();
PhantomReference pr = new PhantomReference (object, queue);
程序可以通过判断引用队列中是否已经加入了虚引用,来了解被引用的对象是否将要被垃圾回收。如果程序发现某个虚引用已经被加入到引用队列,那么就可以在所引用的对象的内存被回收之前采取一些程序行动。

应用场景:可用来跟踪对象被垃圾回收器回收的活动,当一个虚引用关联的对象被垃圾收集器回收之前会收到一条系统通知。
 

过早优化是万恶之源,考虑可靠性、正确性和代码可读性才是大多数应用开发最重要的因素

在日常编程中,保证程序的可读性、可维护性,往往比所谓的最优性能更重要

静态类型:编译期检查
动态类型:运行期检查
public class MyDynamicProxy {
    public static  void main (String[] args) {
        HelloImpl hello = new HelloImpl();
        MyInvocationHandler handler = new MyInvocationHandler(hello);
        // 构造代码实例
        Hello proxyHello = (Hello) Proxy.newProxyInstance(HelloImpl.class.getClassLoader(), HelloImpl.class.getInterfaces(), handler);
        // 调用代理方法
        proxyHello.sayHello();
    }
}
interface Hello {
    void sayHello();
}
class HelloImpl implements  Hello {
    @Override
    public void sayHello() {
        System.out.println("Hello World");
    }
}
 class MyInvocationHandler implements InvocationHandler {
    private Object target;
    public MyInvocationHandler(Object target) {
        this.target = target;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        System.out.println("Invoking sayHello");
        Object result = method.invoke(target, args);
        return result;
    }
}

 

 
 
HashMap 的性能表现非常依赖于哈希码的有效性,请务必掌握 hashCode 和 equals 的一些基本约定,
比如:
equals 相等,hashCode 一定要相等。
重写了 hashCode 也要重写 equals。
hashCode 需要保持一致性,状态改变返回的哈希值仍然要一致。
equals 的对称、反射、传递等特性
 

ConcurrentHashMap的实现, 

 
 
需要结合java疯狂讲义,仔细看一遍,
 
 
需要结合java疯狂讲义和JVM,仔细看一遍,
 
 
接口:定义接口规范,API定义和实现分离,多继承,函数式接口
抽象类:代码重用,定义流程规范,不能实例化,单继承
 
 结合菜鸟教程和java设计模式,重新复习

模块二 Java进阶 (16讲)

synchronized和ReentrantLock等机制等基本使用与案例
掌握synchronized、ReentrantLock底层实现;理解锁膨胀、降级;理解偏斜锁、自旋锁、轻量级锁、重量级锁等概念;
掌握并发包中java.util.concurrent.lock各种不同实现和案例分析
结合《Java并发编程实践》进行复习
线程安全需要保证几个基本特性:
原子性:简单说就是相关操作不会中途被其他线程干扰,一般通过同步机制实现
可见性:是一个线程修改了某个共享变量,其状态能够立即被其他线程知晓,通常被解释为将线程本地状态反映到主内存上,volatile就是负责保证可见行的。
有序性:是保证线程内串行语义,避免指令重排等
锁的持有是以线程为单位而不是基于调用次数
 
 
 
会报错
 
 
 
 
concurrent的组成部分:
1、提供了比synchoronized更加高级的同步结构,包括CountDownLatch、CyclicBarrier、Semaphore等,可以实现更加丰富的多线程操作,
比如利用Semaphore作为资源控制器,限制同时进行工作的线程数量。
2、各种线程安全的容器,比如:ConcurrentHashMap,有序的ConcurrentSkipListMap,或者通过快照机制,实现线程安全的动态数组CopyOnWriteArrayList
3、各种并发队列实现,如各种BlockedQueue实现,比较典型的ArrayBlockingQueue、SynchorousQueue或针对特定场景的PriorityBlockingQueue
4、强大的Executor框架,可以创建各种不同类型的线程池,调度任务运行等,绝大部分情况下,不再需要自己从头实现线程和任务调度器
 
理解具体设计、实现和能力
再深入了解一些比较典型工具类的适用场景、用法甚至是原理,并熟练写出典型的代码用例
 
Concurrent、CopyOnWrite和Blocking的区别:
Concurrent类型没有类似CopyOnwrite之类容器相对较重的修改开销
但是,凡事有代价,Concurrent往往提供了较低的遍历一致性
弱一致性:当迭代器遍历时,如果容器发生修改,迭代器仍然可以继续进行遍历。
弱一致性的另一个体现是:size等操作准确性是有限等,未必是100%准确
与此同时,读取的性能具有一定的不确定性

 

 

 

有两个特别的Deque实现,ConcurrentLinkedDeque和LinkedBlockingDeque。

BlockingQueue都是基于锁实现的,

ConcurrentLinkedDeque则是基于CAS的无锁技术,不需要在每个操作时使用锁,所以扩展性表现要更加优异。

 

第21讲 | Java并发类库提供的线程池有哪几种? 分别有什么特点?

1、掌握Executor框架的主要内容,至少了解组成与职责,掌握基本开发用例中的使用。

2、对线程池和相关并发工具类型对理解,甚至是源码层面对掌握

3、实践中有哪些常见问题,基本的诊断思路是怎样对

4、如何根据自身应用特点合理使用线程池

 
 
 
 
 
 
 
 
 
程序计数器
java虚拟机栈
方法区
运行时常量池
本地方法栈
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

周末福利 (2讲)

1、技术素养好,能够进行深度思考,而不是跳脱的夸夸其谈
2、职业精神,是否表现出认真对待每一个任务
3、是否主动

结束语 (1讲)

 

 

 

posted @ 2019-09-11 18:53  lakeslove  阅读(743)  评论(0编辑  收藏  举报