Java学习笔记

JVM

常用

-Xverify:none
-Xmx
-Xms
-Xmn

JVM运行模式

JVM的锁

偏向锁

如果第一个线程获取到了锁,在执行过程中,没有其他线程竞争,那持有锁的线程就不需要同步

轻量级锁

如果有竞争,偏向锁升级为轻量级锁,轻量级锁使用的是CAS操作

自旋锁

轻量级锁失效后就升级为自旋锁,未获取到锁的线程不用去到操作系统内核态进行挂起,而是用忙循环来等待,有一个默认的等待次数。如果等待的次数由前一次自旋的时间和锁的拥有者的状态决定,就叫自适合自旋锁

锁消除

JVM发现某些加了锁的地方不可能存在竞争,就直接把这个锁去掉

锁粗化

如果对同一个对象多个函数进行加锁,会频繁对同一个对象上锁解锁,影响性能,所以就应该将锁粗化

MQ

RabbitMQ

producer --> broker customer --> exchange --> queue --> consumer

AMQP基本概念

死信队列

RabbitMQ如何保证消息不丢

Kafka

ack机制

高性能的关键

限流

计数器

利用Redis的Incr,设置过期时间,如果get出来的数大于限额,则拒绝,否则incr. 缺点:在两个时间区间过渡的小区间,会出来超限额的情况,即请求分布不均匀。

滑动窗口

将20s内100个请求的限额分成4个小窗口,则每个小窗口是5s, 不能超过25个请求。设窗口大小为2,则每次统计窗口内的请求数,不能超过50个。 分的小窗口越多,越平滑。

漏桶

固定速度消费,设置一个容器,定时以恒定速率remove元素,而生产元素的速率不变。 如果容器本来没怎么满,这个算法就可以起到一定的削峰平滑作用。 缺点:如果容器本来也快要满了,短时间内涌入太多请求,则会拒绝大部分请求。

令牌桶

固定速度生产令牌,取令牌的速率不固定。 如果容器本来就快要满了,这个算法就可以起到一定的削峰平滑作用。 缺点:如果容器本来也快要空了,短时间内涌入太多请求,获取不到令牌,则会拒绝大部分请求。 这个算法的最大好处是,当发现容器快要空的时候,可以加快令牌的发放速率,可是这样不就压垮了服务吗?

Keytool

keytool -list -v -keystore aaa.jks
keytool -genkey -keyalg RSA -alias selfsigned -keystore aaa.jks -storepass password -validity 360 -keysize 2048
keytool -export -keystore aaa.jks -alias signFiles -file aaa.cer
openssl pkcs12 -in keystore.p12 -nokeys -out aaa.crt

Maven

mvn clean package -o
mvn dependency:source
-Dmaven.test.skip=true
mvn source:jar install
mvn dependency:resolve -U

Gradle

package into a fat jar

jar {
    manifest {
        attributes "Main-Class": "io.github.zhengyhn.pan.PanClientCommand"
    }

    from {
        configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
    }
}

面试

微服务

设计的原则

CAP理论

BASE理论

这是针对同时满足AP的情况下的一个理论。由eBay提出。

Java

java -XX:+PrintCommandLineFlags -version

-XX:InitialHeapSize=134217728 -XX:MaxHeapSize=2147483648 -XX:+PrintCommandLineFlags -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseParallelGC
openjdk version "1.8.0_242"
OpenJDK Runtime Environment (AdoptOpenJDK)(build 1.8.0_242-b08)
OpenJDK 64-Bit Server VM (AdoptOpenJDK)(build 25.242-b08, mixed mode)

其中UseCompressedClassPointers表示,虽然JVM是64位的,但是使用压缩的类指针,还是4个字节。而UseCompressedOops表示,普通ordinary object pointer也是使用4个字节。

不通过构造函数也能创建对象吗?

  1. 用 new 语句创建对象,这是最常见的创建对象的方法。 (2) 运用反射手段,调用 java.lang.Class 或者 java.l ang.reflect.Constructor 类的 newInstance() 实例方法。 (3) 调用对象的 clone() 方法。 (4) 运用反序列化手 段,调用 java.io.ObjectInputStream 对象的 readObject() 方法。 (1)和(2)都会明确的显式的调用构造函数 ;(3)是在内存上对已有对象的影印,所以不会调用构造函数 ;(4)是从 文件中还原类的对象,也不会调用构造函数。

引用类型

单例模式

Spring

AOP的原理

BeanFactory与FactoryBean

解决循环依赖的方式

核心要点:通过增加中间态。new --> 初始化 --> 填充属性之后实例化 如果是构造器注入,则无法解决循环依赖问题,因为构造器注入要求注入的对象必须是实例化之后的。 三级缓存:

public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
	...
	// 从上至下 分表代表这“三级缓存”
	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256); //一级缓存
	private final Map<String, Object> earlySingletonObjects = new HashMap<>(16); // 二级缓存
	private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16); // 三级缓存
	...
	
	/** Names of beans that are currently in creation. */
	// 这个缓存也十分重要:它表示bean创建过程中都会在里面呆着~
	// 它在Bean开始创建时放值,创建完成时会将其移出~
	private final Set<String> singletonsCurrentlyInCreation = Collections.newSetFromMap(new ConcurrentHashMap<>(16));

	/** Names of beans that have already been created at least once. */
	// 当这个Bean被创建完成后,会标记为这个 注意:这里是set集合 不会重复
	// 至少被创建了一次的  都会放进这里~~~~
	private final Set<String> alreadyCreated = Collections.newSetFromMap(new ConcurrentHashMap<>(256));
}

Spring实现单例模式

SpringBoot自动配置的原理

Tomcat三种模式

undertow

final

线程池

ThreadLocal

sleep, yield, join, wait, notify, notifyAll

代理模式

CAS

ABA问题

IO模型

每次IO,都要经历两步

协程

是一种协作式的用户态线程。以前,线程和进程都是抢占式执行的,是操作系统自动帮我们切换,让我们感觉是同步进行的。协程是用户进程手动切换,省资源,速度快。

Kafka高吞吐揭秘

注解

有这么三种:

for循环直接删除ArrayList中的特定元素

MyBatis原理

Maven的生命周期

普通内部类与静态内部类

Java类的初始化顺序

基类静态变量和基类静态代码块(按代码的先后位置) --> 派生类静态变量和基类静态代码块(按代码的先后位置) --> 基类初始化块和成员变量 --> 基类构造函数 --> 派生类初始化块和成员变量 --> 派生类构造函数

ArrayList和LinkedList的区别

HashMap和HashTable的区别

LinkedHashMap

TreeMap实现一致性哈希

CopyOnWriteArrayList

对象占用空间

Object ob = new Object(); 

这样在程序中完成了一个Java对象的生命,但是它所占的空间为:4byte+8byte。4byte是栈中保存引用的所需要的空间,而那8byte则是Java堆中对象的信息。

为什么要有hashCode

当你把对象加入HashSet时,HashSet会先计算对象的hashcode值来判断对象加入的位置,同时也会与其他已经加入的对象的hashcode值作比较,如果没有相符的hashcode,HashSet会假设对象没有重复出现。但是如果发现有相同hashcode值的对象,这时会调用equals()方法来检查hashcode相等的对象是否真的相同。如果两者相同,HashSet就不会让其加入操作成功。如果不同的话,就会重新散列到其他位置。(摘自我的Java启蒙书《Head fist java》第二版)。这样我们就大大减少了equals的次数,相应就大大提高了执行速度。

在以下4种特殊情况下,finally块不会被执行:

在finally语句块中发生了异常。 在前面的代码中用了System.exit()退出程序。 程序所在的线程死亡。 关闭CPU。

synchronized

是某个对象实例内,synchronized aMethod(){}可以防止多个线程同时访问这个对象的synchronized方法(如果一个对象有多个synchronized方法,只要一个线 程访问了其中的一个synchronized方法,其它线程不能同时访问这个对象中任何一个synchronized方法)。这时,不同的对象实例的 synchronized方法是不相干扰的。也就是说,其它线程照样可以同时访问相同类的另一个对象实例中的synchronized方法;

== 和 equals有什么区别

== 是一个运算符,如果有一边是基本类型,则比较的是值。如果两边都是引用类型,则比较的是地址。 equals是对象的一个方法,Object类默认的实现是比较两者的地址,一般都会重写这个方法,具体以重写的逻辑为准。 像Integer重写的方法,如果传进来的是基本类型,会进行自动装箱,然后比较类型,再比较值。

Synchronized和ReenTrantLock对比

AQS

是一个抽象类AbstractQueuedSynchronized,定义了一些同步的基础组件,比如CAS,compareAndSet,tryAcquire, tryRelease等,ReenTrantLock的实现就是聚合了AQS的一个子类

ReadWriteLock

ReentrantReadWriteLock维护了2个锁,一个是读锁(共享锁),一个是写锁(排他锁),只要有写的时候就互斥,不能读也不能写。

Snippets

        import java.util.Arrays;
        int[] first = new int[26];
        Arrays.fill(first, 0);

收藏

https://www.processon.com/view/link/5c4ea49ae4b08a7683b74d72

springboot知识图谱 思维导图


https://www.processon.com/view/link/5c6b68b5e4b0641c83fa3708

rocketmq-core 思维导图


https://www.processon.com/view/link/5c6fb06be4b07fada4efec49

并发知识汇总 思维导图


https://www.processon.com/view/link/5c6fad91e4b0f9fba68e7b25

redis基础知识汇总 思维导图。


https://www.processon.com/view/link/5c6fae7fe4b0c4e2165d80c1

机器学习实战笔记 思维导图


https://www.processon.com/view/link/5c6faec5e4b08a7683cb3374

Python学习笔记 思维导图


https://www.processon.com/view/link/5c6faf2fe4b08a7683cb34b7

spring boot admin 思维导图


https://www.processon.com/view/link/5c6faf4ae4b0f9fba68e8060

spring boot actuator 思维导图