码出高效 Java开发手册
2022-03-22 09:30:36 0 举报
AI智能生成
登录查看完整内容
码出高效Java开发手册-阿里巴巴,知识脉络以及读书笔记,方便回顾知识点
作者其他创作
大纲/内容
如果机器字长为n,那么一个数的原码就是用一个n位的二进制数,其中最高位为符号位:正数为0,负数为1。剩下的n-1位表示该数的绝对值。
原码
反码
正数的补码是其本身复数补码也非常的简单,就是在反码的基础上按照正常的加法运算加1
补码
左移<< 右移>>运算中 , 符号位均参与移动 , 除负数往右移动 , 高位补 l 之外,其他情况均在空位处补 0 ,
三个大于号的>>> 无符号向右移动忽略符号 强制向右移动 高位补0
按位取反 ~
按位与 &
按位或 |
按位异或 ^
位运算
0/1的世界
4字节
单精度
8字节
双精度
浮点数
7 组连续的信号量 + 1个校验位 组成ASCii 码表 127位
10 和 13 位 是 \ \ 表示换行 在不同操作系统中 使用的不一样 Windows '\\' unix '\'
ASCii 码表
GB2312 只存储6000多字
GBK GB基础进行扩张
UTF-*
中文
字符集
字符集与乱码
控制单元、指令译码器、指令寄存器
控制单元是 CPU 的大脑,由时序控制和指令控制等组成
指令译码器是在控制单元的协调下完成指令读取、分析并交由运算器执行等操作
控制器
算术逻辑运算单元,即 ALU能够执行算术运算或逻辑运算等各种命令,运算单元会从寄存器中提取或存储数据
运算器
高速缓存
寄存器
CPU
运行程序的空间、与CPU直接进行沟通
内存
CPU 与内存
应用层:HTTP/FTP/SMTP传输层:TCP/UDP网络层:IP链路层:PPP
协议分层
单个 0、 l 是没有意义的,链路层以字节为单位把 0 与 l 进行分组,定义数据帧,写入源和目标机器的物理地址、数据、校验位来传输数据
链路层
IP协议
根据 IP 定义网络地址,区分网段
网络层
数据包通过网络层发送到目标计算机后,应用程序在传输层定义逻辑端口 , 确认身份后,将数据包交给应用程序,实现端口到端口间通信
传输层
传输层的数据到达应用程序时,以某种统一规定的协议格式解读数据。
应用层
网络协议
IP 地址属于网络层,主要功能在 WLAN 内进行路由寻址,选择最佳路由。 IP 报文格式 共 32 位 4 个字节,通常用十进制数来表示。四地址的掩码Ox值班。。表示 255.255.255.0 ,掩码相同,则在同 一子网内。 IP 协议在 IP 报头中记录源 IP 地址和目标 IP 地址
生存时间TTL,每经过一个路由器TTL -1 到0后就废弃
IP报文格式
传输控制协议,是 种面向连接、确保数据在端到端间可靠传输的协议
从编程的角度, TCP 连接的建立是通过文件描述待( File Descriptor ,“) 完成的。通过创建套接字获得一个 fd , 然后服务端和客户端需要基于所获得的 “ 调用不同的函数分别进入监昕状态和发起连接请求。由于臼的数量将决定服务端进程所能建立连接的数量 ,对于大规模分布式服务来说,当 阳 不足时就会出现 、pen too manyfiles ” 错误而使得无法建立更多的连接。为此,需要注意调整服务端进程和操作系统所支持的最大文件句柄数。通过使用 ulimit -n 命令来查看单个进程可以打开文件句柄的数量。
第一行端口号与上层IP来确定通信,开启监听客户端发送 SYN=1 , 服务端接受 ACK = 1 ,客户端发送 SEQ = y ack+1 这样用来保证可靠性
报文格式
TCP建立链接
客户端发送 TCP报文FIN字段设置为1 seq = u
服务端 发送 ack = 1 seq = u+1
服务端发送 FIN = 1
客户端回应ACK
四次挥手
客户端发送断开之后、服务器ACK 在此之后的一段时间称为 close_wate
可以在服务器上修改配置 telsysctl.conf
服务器发出断开后 客户端响应 , 会有一线段时间 成为 time_wait 等待断开
断开链接
TCP/IP
跨站脚本攻击
页面使用脚本获取后台数据
解决:Jsoup
XSS
跨站请求伪造
同一浏览器可以获取用户token,会造成恶意进攻
解决1:CSRF Token 验证,利用浏览器的同源限制,在 HTTP 接口执行前验证页面或者 Cookie 中设置的 Token ,只有验证通过才继续执行请求。2:人机交互 ,比如在调用上述网上银行转账接口时校验短信验证码。
CSRF
SSL 协议工作于传输层与应用层之间,为应用提供数据的加密传输,可以理解接受到HTTP报文之后进行SSL加解密这个操作
HTTP+SSL(安全套接字层)
将密码分为公钥和私钥私钥是用来对公钥加密的信息、进行解密的,是需要严格保密的。公钥是对信息进行加密,任何人都可以知道,包括黑客。
非对称加密
权威认证的HTTPS证书
CA机构
1:浏览器向服务器发送请求,请求中包括浏览器支持的协议,并附带一个随机数。2:服务器收到请求后,选择某种非对称加密算法,把数字证书签有公钥、身份信息发送给浏览器,同时也附带一个随机数。3:浏览器收到后、验证证书的真实性,用服务器的公钥发送握手信息给服务器。4: 服务器解密后 , 使用主前的随机数计算出,对称加密的密钥 , 以此作为加密信息并发送。5: 后续所有的信息发送都是以对称加密方式进行的。
访问过程
HTTPS
信息安全
计算机基础
以对象模型为核心 , 丰富模型的内涵,扩展模型的外延,通过模型的行为组合去共同解决某一类问题,抽象能力显得尤为重要 , 封装是一种对象功能内聚的表现形式,使模块之间辑合度变低,更具有维护性,继承使子类能够继承父类,获得父类的部分属性和行为,使模块更有复用性 ; 多态使模块在复用性基础上更加有扩展性,使运行期更有想象空间。
面向对象思维
我是谁 toString() 相当于名片书写
getClass()
我从哪里来
Object()
对象的消亡
finalize()
只复制当前对象的所有基本数据类型,以及相应的引用变量,但没有复制引用变量指向的实际对象
浅拷贝
浅拷贝和彻底深拷贝之间
一般深拷贝
成功 clone 个对象之后,此对象与母对象在任何引用路径上都不存在共享的实例对象 ,但是引用路径递归越深,越接近 JVM底层对象
彻底深拷贝
clone 默认浅拷贝,要使用深拷贝需要重写方法
clone()
每个类独有的、世界因你而不同
hashCode()/equals()
线程之间的协作
wait()/notify()
经典Object类
继承
封装
子类实现接口 , 或者继承父类时 , 保持方法签名完全相同,实现不同的方法体 , 是垂直方向上行为的不同实现
override -- 重写
方法名称是相同的,但是参数类型或参数个数是不相同的,是水平方向上行为的不同实现
overload -- 重载
多态是指在编译层面无法确定最终调用的方法体 , 以覆写为基础来实现面向对象特性,在运行期由 JVM 进行动态绑定 , 调用合适的重写方法体来执行
多态
经典特性
abstract - interface
抽象类:对同类事物具体的抽象、属于模板式设计
接口实现类要有能力去实现并执行接口 中定义的行为、属于契约式设计
接口与抽象类
任何一个类都可以在内部定义另外一个类,内部类作为类的一个属性
static class StaticinnerClass {} ;
静态内部类
private class InstancelnnerClass {} ;
成员内部类
方法或者表达式内部
局部内部类
(new Thread(){} ).start()
匿名内部类
内部类
控制访问权限
this() 子类构造方法 super() 父类构造方法
this\\super
实例方法
静态方法
静态代码块
类内方法
override
如果父类定义的方法达不到子类的期望,那么子类可以重新实现方法覆盖父类的实现
返回值能够向上转化为父类的返回值
异常向上抛出
方法名和参数必须一致
非静态、非final、非构造
重写
初识Java
面向对象
一般为动词,与参数组成动宾结构
FileInputStream
命名体现代码元素
命名最好望文知义
作用域内保持不变的值、用public static final修饰
public static final String GLOBAL CONSTANT = ” shared in global ” ;
全局:采用全部大写
final String methodConstant = ” shared in method ” ;
局部:采用小写
禁止使用魔法值,应该在外部定义
常量
小驼峰格式
变量
缩进:Tab
任何二目、三目运算符左边都需要加一个空格
注释双斜线与内容应该有一个空格
方法参数入参是,逗号后面都应该有一个空格
没必要增加空格与上一行对齐
大括号中间无需加空格
左右小括号与内部内容无需加空格
左大括号前加空格
空格
方法定义之后、属性定义与方法之间、不同逻辑、不同语义、不同业务的代码之间都需要通过空行来分隔。
空行
第二行与第二行缩进4个空格
运算符与下文一起换行
在括号前不要换行
方法调用中的多个参数需要换行时 , 在逗号后换行。
换行
方法行数最好保持80行
if else for while 后必须加大括号
条件表达式中不允许有赋值操作
循环嵌套不循序操作3层
避免采用取反运算逻辑
空制语句
代码展示与风格
代码风格
JVM ->编译执行字节码
cafe baby 代表Java文件
0X37代表JDK11版本
.class 文件 ,打开是二进制文件,可转化为16进制后每个16进制表示二进制流,代表一个操作指令
ALOAD_0 - 0010 1010 - OX2a
POP - 0101 0111 - Ox57
A代表引用类型操作、I代表整数类型操作 其他类型均是其类型的首字母
JVM中也有助记符
将局部变量加载到操作栈中(ILOAD、ALOAD)
从操作栈顶存储到局部变量表中(ISTORE、 ASTORE)
ICONST 加载的是 1 ~ 5 的数(!CONST 与 BIPUSH 的加载界限)
BIPUSH ,即 Byte Immediate PUSH ,加载 -128 ~ 127 之间的数
SIPUSH ,即 Short Immediate PUSH ,加载 -32768 ~ 32767 之间的数
LDC ,即 Load Constant ,在 -2147483648 ~ 2147483647 或者是字符串时,JVM采用 LDC 指令压入枝中。
将常量加载到操作栈顶、极为高频 (ICONST、 BIPUSH 、 SIPUSH 、 LDC)
加载或存储指令
对两个操作栈帧上的值进行运算,并把结果写入操作栈顶,如 IADD 、 IMUL 等。
指令运算
显式转换两种不同的数值类型。如 I2L 、 D2F 等
类型转换指令
NEW 、 NEWARRAY
创建对象
GETFIELD 、 PUTFIELD 、 GETSTATIC
访问属性
检查实例类型指令
对象创建与访问 指令
POP POP2
出栈
DUP
复制栈顶元素并且入栈
操作栈管理指令
INVOKEYIRTUAL 指令 调用对象的实例方法。
INVOKESPECIAL 指令 调用实例初始化方法、私有方法、父类方法等。
INVOKESTATIC 指令 调用类静态方法。
RETURN 返回VOID类型
方法调用与返回
NM 使用方法结构中的 ACC_SYNCHRONIZED 标志同步方法 , 指令集中有MONITORENTER 和 MONJTOREXIT 支持 synchronized 语义。
同步指令
LINENUMBER 存储了字节码与源码行号的对应关系 方便调试
LOCALVARIABLE 存储当前方法中使用到的局部变量表。
其他
字节码主要指令
Java文件 -- 词法解析 -- 语法解析 -- 语义分析 -- 生成字节码
通过空格分隔 出单词 、 操作符、控制符等信息 , 将其形成 token 信息流 ,传递给语法解析器
词法解析
把词法解析得到的 token 信息流按照 Java 语法规则组装成一棵语法树
语法解析
检查关键字使用是否合理、类型是否匹配、作用域是否正确,语义分析完成后可生成字节码
语义分析
Java文件编译成字节码的编译过程
解释执行
JIT编译执行
解释器在启动时先解释执行,省去编译时间。JVM 通过热点代码统计分析 , 识别高频的方法调用、循环体、公共模块等,基于强大的 JIT 动态编译技术,将热点代码转换成机器码,直接交给 CPU执行。
两者混合
字节码加载
字节码
ClassLoader 将class文件加载到内存中、双亲委派模型
运行时核心基础设施模块
读取类文件产生的二进制字节流并转化为特定的数据格式初步校验 cafe baby魔法值、常量、文件长度、父类,然后创建对应的 java.lang.Class 类型
加载
验证、准备、解析 三个步骤
验证:更为详细的校验,final修饰是否正确,类型引用是否正确、静态变量是否合理
准备: 为静态变量分配内存、设置默认值
解析:类和对象之间的引用正确性
链接
执行类构造器clinit方法
如果其中赋值依赖其他类、会立刻解析其他类
初始化
类加载器
由C++ 实现
Bootstrap 类加载器:由JVM启动时候创建、负责装载最核心的类 Object 、 System 、 String 等;
JDK9:platform 类加载器:平台加载器、加载加密、压缩、XML解析等方法
JDK9之前:Extension ClassLoader 类加载器 功能与platform 相似
Application ClassLoader : 加载用户定义的class路径下的类
用户也可以自定义classLoader
这个类加载了吗? -- 向上询问,直至BootStrap我是否可以下载这个类? -- Bootstrap向下询问,尝试可加载
类加载器具有等级制度、但非继承关系,是以组合的关系来进行复用低层次的不能覆盖高层次的,故有了双亲委派模型
加载顺序
类加载过程
简图
OOM 故障发源地、存储着几乎所有对象实例、垃圾收集器自动回收
-Xms256M Xmx512M 最小堆 - 最大堆-X表示JVM参数 ms表示内存memory start 初始 mx表示memory max 最大建议两者调成一致的,因为堆内存存在压缩与释放,如果发生GC,频发压缩、释放会对计算机产生压力
伊甸园、幸存者 1:2新创建对象在伊甸园区,伊甸园填满后会触发YGC,没有引用的对象进行清除,存活的对象放到幸存者区
每个对象都有一个计数器 发成YGC后会进行+1,直到 -XX:MaxTenuringThreshold 会放到老年区
新生代
接受新生代存不下的对象、
老年代也放不下会触发FGC、如果依旧放不下会触发OOM -XX:+HeapDumpOnOutOfMemoryError ,让JVM 遇到 OOM 异常时能输出堆内信息,特别是对相隔数月才出现的 OOM 异常尤为重要。
老年代
分为新生代、老年代,对象创建在新生代、到了暮年后转为老年代
Heap堆
在本地内存分配、类元信息、字段、静态属性、方法、常量
Metaspace 元数据
方法开始时,只有栈顶的栈帧时有效的正在执行的方法称为当前方法 , 栈帧是方法运行的基本结构。正常运行:结束后指向下一个栈帧异常报错:进行回溯,返回地址通过异常处理表确定
是存放局部变量和方法参数的区域字节码指令中的 STORE 指令就是将操作栈中计算完成的局部变量写回局部变量表的存储空间内。
局部变量表
例如: 数据压栈BIPUSH 、数据加载 ILOAD
方法执行过程中,对具体运算进行压栈和出栈,来进行数据运算
i++ 先进行数据加载,然后进行运算
++i 先运算字节码,然后进行结果赋值
两者汇编指令不一样
i++ 和 ++i 的区别
操作栈
每一个栈帧对应的是一个常量池的引用,目的是支持对应方法调用过程的连接
动态连接
正常返回字节码状态 return ireturn 等
错误、异常退出
退出
返回值压入上层调用栈帧
异常信息抛给能够处理的栈帧
PC 计数器指向方法调用后的下一条指令
退出三种方式
返回地址
栈帧
JVM Stack 虚拟机栈
本地方法栈为 Native 方法服务、调用系统方法
Native Method Stacks (本地方法栈 )
由于CPU分片运行,PC计数器就会记录当前执行的状态,以供下次继续运行
Program Counter Register (程序计数寄存器)
JVM 内存结构
找不到对象,开启类加载机制,加载成功后开启,在堆中分配内存
分配完成内存后,将实例对象压入虚拟机栈顶
New
将栈顶赋值到引用变量,此时两个指针指向对象,一个进行赋默认值,另一个设置为句柄进行方法调用
dup
调用对象实例方法,通过栈顶的引用变量调用<init>方法
invokespecial
字节码角度
确认类无信息是否存在,存在即引用,不存在及加载字节码
分配对象内存
设定默认值。
设置对象头
执行 init 方法
对象创建角度
Object o = new Object() javap -verbose -p *.class 文件进行分析
对象实例化
存活对象: 有引用的对象
STW:垃圾回收期间,整体JVM停止工作,程序卡顿
相关概念
将有引用的对象进行标记,那么没被标记的就会清除
标记-清除
将内存分为1:1,将有引用的进行标记,然后复制到另一块区域,然后清除该区域
标记- 拷贝
标记存活的对象,然后将存活对象整理到内存空间的一端,形成连续的已使用空间 , 最后把已使用空间之外的部分全部清理掉
标记-压缩
产生STW
CMS
对象引用、回收
SATB
三色标记
垃圾回收算法
YGC 清除方式、单线程的方式
标记-整理 标记-拷贝 两种方式
Serial
多线程方式进行处理
并发的进行 标记-清除
产生游离对象
内存划分区域,分为四类Eden 、Survivor 、 Old 、 Humongous(Old中的大对象)优先回收垃圾最多的区域
标记-拷贝
G1内存分区
垃圾回收器
垃圾回收
工作遇到Java heap space 报错、进行分析
0:查看内存当前线程 ps -aux|grep serviceName
#出现 OOME 时生成堆 dump: -XX:+HeapDumpOnOutOfMemoryError#生成堆文件地址:-XX:HeapDumpPath=/opt/jvmlogs/
使用Jprofile 分析dump 文件
可以看到那些数据结构占用空间大小,进行数据分析
2:DUMP 文件分析
DUMP 文件分析
调优
走进JVM
线性结构
树形结构
图形结构
hash结构
数据结构
常数级 0(1 )、对数级 O(logn)、线性级 0(n)、线性对数级O(nlogn ) 、平方级 O(n^2)、立方级 O(n^3)、指数级 0(2^n)
时间复杂度
类图:红色代表接口 , 蓝色代表抽象类 , 绿色代表并发包中的类,灰色代表早期线程安全的类
第一类是按照单个元素存储的 Collection(set、List、Queue、Map实现)
第二类是按照 Key-Value 存储的 Map
主要分为两大类
ArrayList
LinkedList
List集合
Queue (队列)是一种先进先出的数据结构,队列是一种特殊的线性表,它只允许在表的 端进行获取操作,在表的另一端进行插入操作。当队列中没有元素时,称为空队列。自从 BlockingQueue (阻塞队列)问世以来,队列的地位得到极大的提升,在各种高并发编程场景中,由于其本身 FIFO 的特性和阻塞操作的特点,经常被作为Buffer (数据缓冲区)使用。
Queue集合
key-value
Map集合
不允许出现重复元素的集合类型
hashSet
TreeSet
LinkedHashSet
Set集合
集合框架图
1:初始化时候,传入多大的参数就生成多大的Object[] 数组
2:扩容新的容量 int newCapacity = oldCapacity + (oldCapacity >> 1); 位运算右移一位会产生另外一个正数,超过最大位就比他小,因此后面进行了判断,如果new小于old,那么进行size + 1 操作
3:如果长度位1000,那么初始化需要扩容13次才可以完成,如果直接初始化1000,就不会扩容,进行多余计算,如果不注意内存分配,产生OOM问题
HashMap不会再new的时候创建内存,而是在第一次put时候进行创建初始大小
capacity 容量大小
LoadFactor 负载因子 , *capacity 与实际存储进行对比,判断是否需要扩容
两个重要参数,Capacity 和 Load Factor
HashMap
集合初始化
Arrays.asList() 转换以后不能使用其 add/remove/clean 方法 否则会抛出UnsupportedOperationException 异常
Arrays
数组与集合
List<?> 代表集合通配符、可以接受任何类型的集合引用和赋值,但是不能添加,只能remove和clear一般作为参数来接收外部的集合,或者接收不知道返回类型的集合
List、List<Object>、List<?>
T只能放一种类型
<? extends T> 只能放T和子类
<? super T> 只能放 T和父类
List<T> 、<? extends T>、 <? super T>
集合与泛型
Comparable 是自己和自己进行比较时候会调用的方法,比较方法是compareTo
Comparator 是 自己和其他元素对比调用的方法,调用的方法是compare
约定俗成,不管是 Comparable 还是 Comparator , 小于的情况返回 -1 , 等于的情况返回 0 ,大于的情况返回 l 。
Comparable 和 Comparator
hashCode 和 equals 用来标识对象 , 两个方法协同工作可用来判断两个对象是否相等。
任何情况下 重写equals的同时必须重写hashCode
hashCode 和 equals
元素比较
fail-fast 机制
Map 类取代了旧的抽象类 Dictionary ,拥有更好的性能。没有重复的 Key ,可以有多个重复的 Value。Value 可以是 List 、 Map 、 Set 类对象。KV 是否允许为 null ,以实现类约束为准。
提供了三个特殊方法 keySet()\\values()\\entrySet()
注意点:ConcurrentHashMap 的key和value都不允许为空
了解到的Map集合
Map 类的特点
树
每个节点最多有两个叶子
平衡二叉树
左节点<根节点<右节点
容易失衡,导致深度过深
二叉查找树
二叉树基础上添加左旋、右旋操作,深度不会加深
AVL树
AVL树每次都要判断旋转、红黑树深度超过广度的二倍才会旋转
AVL是绝对的平衡、红黑树是相对平衡
红黑树
table 存储所有节点的数据的数组
slot 哈希槽,类似table[i] 这样的位置
bucket 哈希桶,类似table[i]上存储元素形成的表或者数的集合
图解
存储概念
当前数量>最大数量*负载因子 就会进行扩容
16 是默认容量大小 0.75 是默认负载因子
负载因子
扩容
后续总结博客中
迁移与源码分析
线程安全,推荐使用,完全可以提点HashMap, 使用了 lock-free 技术减少锁的影响
取消分段锁,降低冲突概率
引入红黑树
使用更加优化的方式统计集合内部元素数量
JDK11的优化
后续会总结到博客中
源码分析
ConcurrentHashMap
ReadWriteLock
Map 类集合
数据结构与集合
Thread、Runnable 接口、Callable 接口
NEW新建
调用start()后
runnable 就绪
run()执行
running 运行
获取不到锁,无法运行
同步阻塞
sleep()、 join()
主动阻塞
wait()
等待阻塞
blocked 阻塞
run()结束后
dead 终止
线程状态
1:数据单线程可见
2:只读对象
3:线程安全类
线程同步类
并发集合类
线程管理类
锁相关类
4:同步与锁机制
如何保证安全
线程安全
继承关系图
ReentrantLock
AQS
CountDownLatch
Semaphore
CyclicBarrier
StampedLock
Lock
锁(JUC)
在方法签名处加 synchronized 关键字
对对象、类进行同步
原则是锁的范围尽可能小
synchronized
JVM实现
同步代码块中会使用 monitorenter 及 monitorexit 两个字节码指令获取和释放 monitor。如果使用 monitorenter 进入时 monitor 为 0 ,表示该线程可以持有 monitor 后续代码,并将 monitor 加 l ,如果当前线程已经持有了 monitor , 那么 monitor 继续加 l ;如果monitor 非 0 , 其他线程就会进入阻塞状态。
JVM找到找到对应对象的 monitor
00\\01\\10\\11
偏向锁、轻量级锁、重量级锁、还提供自动的升级和降级机制
实现原理
同步代码块
防止指令重排序
时钟顺序先后
happen before
计算机并不会根据代码顺序按部就班地执行捆关指令、将相关指令信息进行合并
指令优化-指令重排序
每个线程都有独占的内存区域 span class=\"fontstyle0\" style=\
适用于一写多读的场景
只能保证线程可见,不能保证线程同步
volatile保证线程可见性防止指令重排序
信号量同步
线程同步
如果等于 0 ,则任务执行完之后 ,没有任何请求进入时销毁线程池的线程,如果大于 0 ,即使本地任务执行完毕,核心线程也不会被销毁。
corePoolSize 表示常驻核心线程数
如果待执行线程数大于最大线程数,就会放缓存队列中
maximumPoolSize 表示线程池能够容纳同时执行的最大线程数
当空闲时间达到 keepAliveTime 值时,线程会被销毁,直到只剩下 corePoolSize 个线程为止,避免浪费内存和旬柄资源。
keepAliveTime 表示线程池中的线程空闲时间
TimeUnit 表示时间单位
当请求的线程数大于 maximumPoolSize时 , 线程进入 BlockingQueue 阻塞队列。
workQueue 表示缓存队列
它用来生产一组相同任务的结程。线程池的命名是通过给这个 factory 增加组名前缀来实现的。
threadFactory span class=\"fontstyle0\" style=\
保存到数据库进行 削峰填谷。在空间时提取出来执行。
转向某个提示页由。
打印日志
handler span class=\"fontstyle0\" style=\
参数
创建持有足够线程的线程池支持给定的并行度 , 并通过使用多个队列减少竞争
Executors.newWorkStealingPool()
maximumPoolSize 最大可以至 Integer.MAX_VALUE, 是高度可伸缩的线程池 ,容易造成OOM
Executors.newCachedThreadPool()
Executors.newScheduledThreadPool()
创建个单线程的线程池,相当于单线程串行执行所有任务 , 保证接任务的提交顺序依次执行。
Executors.newSingleThreadExecutor()
输入的参数即是固定线程数,既是核心线程数也是最大线程数 , 不存在空闲线程, 所以 keepAliveTime 等于 O使用的是LinkedBlockingQueue 等待队列,是无界队列,也会造成OOM问题
Executors.newFixedThreadPool()
另外,Executors 中默认的线程工厂和拒绝策路过于简单,通常对用户不够友好
创建
自定义工厂创建
创建工厂
AbortPolicy 默认、丢弃任务并抛出RejectedExecutionException异常
DiscardPolicy,丢弃任务,不抛出异常
DiscardOldestPolicy 丢弃掉队列中最久的任务
CallerRunsPolicy 直接调用run方法,放弃线程池的方式
默认的四种拒绝策略
使用自定义拒绝策略,可以记录日志或者数据库或者队列中,等空闲时候再处理
拒绝策略
博客更新
源码
线程池
Object o = new Object(); GC可达,必不可能回收
强
OOM之前,垃圾回收器会在回收考虑范围内
软
YGC 就会被回收
弱
被回收时提供系统通知
虚
引用类型
set、get、remove
使用完成的变量应该快速remove掉,避免内存泄漏
重要方法
ThreadLocal
并发与多线程
用于在 NM 上启动测试框架 , 统一命令行、 Gradle 和 Maven执行测试入口
JUnit Platform
包含 JUnit5.x 全新的编程模型和扩展机制
JUnit Jupiter
用于在新的框架中兼容运行 JUnit3.x 和 JUnit4.x 的测试用例。
JUnit Vintage
三个模块
@Test
@BeforeAll
@AfterAll
@Disabled
@Tag
@DisplayName
注解
常用的断言被封装在 org.junit.jupiter.api.Assertions 类
fail 断言测试失败
assertTrue/assertFalse 断言真假判断
assertEquals 判断是否相等
断言
JUnit5.x
单元测试
throw 是方法内部抛出具体异常类对象的关键字, throws用在方法 signature 上,表示方法调用者可以通过此方法声明向上抛出异常对象无论采用哪种方式处理异常 , 都严禁捕获异常后什么都不做或打印一行日志了事
throw 、 throws 的区别
StackOverflowError、OutOfMemoryError
Error
checked
unchecked
Exception
分类
异常
异常&日志
码出高效
0 条评论
回复 删除
下一页