Java基础
2025-08-19 14:57:41 5 举报
AI智能生成
Java基础整理
作者其他创作
大纲/内容
基本功
数据类型
byte
8位,1字节,默认值0
int
32位,4字节,默认值0
short
16位,2字节,默认值0
long
64位,8字节,默认值0L
char
16位,2字节,默认值'u0000'
float
32位,4字节,默认值0f
double
64位,8字节,默认值0d
boolean
1位,默认值false
自动拆箱/装箱
Integer
深/浅拷贝
深拷贝
例如:序列化和反序列化
浅拷贝
面向对象
equals和==
序列化
通过关键transient可以避免序列化
核心技术
集合
List
ArrayList
数据结构
Object[]数组
线程不安全
复杂度
时间复杂度
随机访问,通过元素序列号get(int index)访问,速度快
内存占用
扩容机制
无参构造创建
有参构造
扩容add()
LinkedList
数据结构
jdk1.7之前循环链表,jdk1.7之后双向链表
线程不安全
复杂度
时间复杂度
通过指针访问,速度相对较慢
内存空间占用
Vector
数据结构
Object[]数组
线程安全
CopyOnWriteArrayList
数据结构
线程安全
Map
HashMap
数据结构
线程不安全
多线程下死循环
HashTable
数据结构
线程安全
ConcurrentHashMap
线程安全
数据结构
Set
异常
try-with- resources(对于必须要关闭的资源使用此方法)
多线程
创建线程的方式
继承Thread(无返回值)
实现Runnable接口(无返回值)
Executor Service,Callable,Future(有返回值)
线程池(ExecutorService)
newCacheThreadPool
newFixedThreadPool
newScheduledThreadPool
newSingleThreadExecutor
ThreadPoolExecutor线程池状态
RUNNING(运行状态,接受新任务,持续处理任务队列里的任务;)
SHUTDOWN(不再接受新任务,但要处理任务队列里的任务)
STOP(不再接受新任务,不再处理任务队列里的任务,中断正在进行中的任务;)
TIDYING(表示线程池正在停止运作,中止所有任务,销毁所有工作线程,当线程池执行 terminated() 方法时进入 TIDYING 状态;)
TERMINATED(表示线程池已停止运作,所有工作线程已被销毁,所有任务已被清空或执行完毕,terminated() 方法执行完成;)
执行步骤
拒绝策略
AbortPolicy(直接抛出异常,阻止系统正常运行)
CallerRunsPolicy(只要线程池未关闭,该策略直接在调用者线程中,运行当前被丢弃的任务。显然这样做不会真的丢弃任务,但是,任务提交线程的性能极有可能会急剧下降)
DiscardOldestPolicy(丢弃最老的一个请求(即将被执行的一个任务),并尝试再次提交当前任务)
DiscardPolicy(该策略默默地丢弃无法处理的任务,不予任何处理)
自定义拒绝策略(RejectedExecutionHandler)
线程数量设置
IO密集型
最佳线程数 = CPU核心数 * (1 / CPU 利用率) = CPU核心数 * (1 + (IO 耗时 / CPU 耗时))
CPU密集型
最佳线程数 = CPU核数 + 1
线程池监控
线程池运行时埋点,每一次运行任务都进行统计
通过锁获取线程池状态,性能较差
定时获取线程池的运行数据
线程生命周期
新建(new)
new了一个Thread
就绪(runnable)
调用了start()方法
运行(running)
开始执行run()方法
阻塞(blocked)
等待阻塞
运行中的线程执行了wait()方法,JVM将线程放入了等待队列中
同步阻塞
运行中的线程获取同步锁时,同步锁被别的线程资源占用,JVM将该线程放入锁池中(lock pool)
其他阻塞
sleep/join
结束(dead)
正常结束
stop()手动结束
容易导致死锁
导致该线程持有的所有锁突然全部释放,可能导致数据不一致
使用退出标志
退出标志的变量需要用volatile修饰
interrupt
处于阻塞状态时抛出异常结束
未处于阻塞时,内部使用标志退出
sleep和wait区别
sleep()
属于Thread类
暂时让出线程资源,但是监控状态一直存在直到指定时间继续运行
线程不会释放锁
wait()
属于Object类
线程放弃对象锁,进入此对象的等待锁定池,只有调用notify()后线程才会调用此对象锁定池中的锁
守护线程(后台线程)
优先级低
通过setDaemon(true)设定此线程为守护线程
Daemon线程产生的线程也是Daemon线程
线程时jvm级别的
生命周期
锁
乐观锁
读多写少
通过版本号
CAS实现
悲观锁
写多读少
Synchronized
AQS框架下先尝试CAS,失败转换为悲观锁
同步锁Synchronized
可以吧任何非null的对象当锁
属于独占锁悲观锁
可重入锁
作用范围
作用于普通方法时,锁的是当前实例(this)
作用于静态方法时,锁的是Class实例
作用于对象实例时,锁的是所有以该对象为锁的代码块
核心方法
Wait Set(哪些调用 wait 方法被阻塞的线程被放置在这里)
Contention List(竞争队列,所有请求锁的线程首先被放在这个竞争队列中)
Entry List(Contention List 中那些有资格成为候选资源的线程被移动到 Entry List 中)
OnDeck(任意时刻,最多只有一个线程正在竞争锁资源,该线程被成为 OnDeck)
Owner(当前已经获取到所资源的线程被称为 Owner)
!Owner(当前释放锁的线程)
实现原理
通过监视器锁(monitor)实现
加锁时执行monitorenter指令,释放锁时执行monitorexit指令
存储位置
对象头
自旋锁
优点
尽可能的减少阻塞
对于锁竞争不激烈的,通过代码块可以大幅提高效率
自旋锁开启
可重入锁(递归锁)
ReentrantLock 和 synchronized
公平锁/非公平锁
非公平锁
JVM 按随机、就近原则分配锁的机制则称为不公平锁
性能更加高
公平锁
公平锁指的是锁的分配机制是公平的,通常先对锁提出获取请求的线程会先被分配到锁
ReentrantLock
读写锁(ReadWriteLock)
共享锁/独占锁
独占锁
共享锁
AQS 的内部类 Node 定义了两个常量 SHARED 和 EXCLUSIVE,他们分别标识 AQS 队列中等待线程的锁获取模式
java 的并发包中提供了 ReadWriteLock,读-写锁。它允许一个资源可以被多个读操作访问,或者被一个 写操作访问,但两者不能同时进行
重量级锁(Mutex Lock)
轻量级锁
偏向锁
分段锁
例如:ConcurrentHashMap
锁优化
减少锁的持有时间
减小锁的粒度
锁分离
锁粗化
锁消除
Semaphore 信号量
AQS
CAS
ABA问题的解决
阻塞队列
原理
当队列中没有数据时,消费端所有线程被挂起
当队列已满时,生产端所有的线程被挂起
队列类别
ArrayBlockingQueue(由数组结构组成的有界阻塞队列)(公平/非公平)
LinkedBlockingQueue(由链表结构组成的有界阻塞队列)(两个独立锁提高并发)
PriorityBlockingQueue(支持优先级排序的无界阻塞队列)((compareTo 排序实现优先))
DelayQueue(使用优先级队列实现的无界阻塞队列)(缓存失效、定时任务 )
应用场景
缓存系统的设计
定时任务调度
SynchronousQueue(不存储元素的阻塞队列)(不存储数据、可用于传递数据)
LinkedTransferQueue(由链表结构组成的无界阻塞队列)
LinkedBlockingDeque(由链表结构组成的双向阻塞队列)
关键字
volatile
变量可见性
禁止重排序
解决可见性和有序性,不能解决原子性
必须满足两个条件才能保障并发环境安全
对变量的写操作不依赖于当前值(变量只能单纯的一次赋值)
该变量没有包含在具有其它变量的不变式中
ThreadLocal
每个线程中都有一个自己的 ThreadLocalMap 类对象,可以将线程自己的对象保持到其中,各管各的,线程可以正确的访问到自己的对象
将一个共用的 ThreadLocal 静态实例作为 key,将不同对象的引用保存到不同线程的ThreadLocalMap 中,然后在线程执行的各处通过这个静态 ThreadLocal 实例的 get()方法取得自己线程保存的那个对象,避免了将这个对象作为参数传递的麻烦
应用场景
资源连接(如数据库连接)
session管理
native
UnSafe
内存管理
普通读写
volatile读写
有序写入
直接操作内存
非常规实例化对象
类加载
偏移量
数组操作
线程调度
CAS操作
内存屏障
其它
对象组成
对象头
数据长度32bit/64bit
Mark Word(存储对象运行时自身的数据)
HashCode(哈希码)
GC分代年龄
锁标志位
线程持有的锁
偏向线程ID
偏向时间戳
对象分代年龄
类型指针
数组长度(对象是数组类型才有)
实例数据
对齐填充
Servlet
0 条评论
下一页