JAVA基础
2020-10-25 17:06:48 0 举报
AI智能生成
java基础
作者其他创作
大纲/内容
面向对象
三大特征
封装
隐藏实现逻辑,只提供接口方法
优点:增强代码复用性,增强代码安全性,人员变动时方便他人接手
继承
从其他类中继承某些方法和变量
优点:增强代码复用性,是多态的基础
缺点:增加了耦合度,低内聚,高耦合
多态
子类的变量可以赋值给父类变量,同一类型表现出不同特征
优点:增强代码的扩展性,以及可维护性。
缺点:无法实现子类特有的功能。
五大原则
单一职责(SRP)
一个类一个方法功能尽量单一,功能越单一复用性会越高
开闭原则(OCP)
开放模块的扩展性,关闭模块的更改
里氏替换(LSP)
父类出现的任何地方都可以由子类代替
依赖倒置(DIP)
上层依赖下层,这样可以任意切换下层实现
接口分离(ISP)
模块间应通过接口分离开而不是强耦合在一起
基本数据类型
八种数据类型
byte、char、boolean、short、int、long、double、float
单精度和双精度
单精度:指浮点位的长度,float浮点位长度为23,double浮点位长度为52
不能用浮点数表示金额
因为浮点数运算会存在精度问题
包装类型
自动装箱拆箱
装箱:int类型可以直接赋值给Integer类型,拆箱:Integer类型可以直接赋值给int
Integer缓存
Integer内部会有一个-128至127范围的缓存,当Integer i=1 integer j = 1时是取缓存对象所以两个是同一地址
各种关键字
transient
被transient修饰的属性不可以被序列化持久化到磁盘
instanceof
判断属性是否是某个类型的
volatile
内存屏障
线程可见性
synchronize
锁机制
final
修饰类
类不可以被继承,设计阶段谨慎考虑
修饰方法
方法不可以被重写但是可以被重构
修饰变量
只可以被赋值一次,修饰基础数据类型,值不可以被修改,修饰引用型变量,引用不可以被更改
static
修饰的变量和方法属于Class,和Class一起加载,并会给变量赋初始值
const
类似于final还未使用
集合类
collection与collections区别
collection是集合的顶层接口,约束集合应该有的方法,而collections是一个集合工具类
set与list区别
set底层是一个无序不重复的集合,list是一个无序重复的集合
ArrayList和LinkedList和Vector的区别
ArrayList底层是数组而LinkedList底层是双链表的形式,vector是通过在方法上加锁来实现线程安全,锁的力度过大
SynchronizedList和Vector的区别
SynchronizedList锁的是mutex而vector锁的是list,扩容也不一样vector是两倍扩容
注解
元注解
@Target
标注注解注解的位置,方法,属性,类,参数
@Retention
用于描述注解的生命周期,表示需要在什么级别保存该注解,即保留的时间长短。
@Documented
描述在使用 javadoc 工具为类生成帮助文档时是否要保留其注解信息。
@Inherited
标注注解是否可以被继承
线程
线程的五种状态
新建
可运行
线程创建后被start,等待争抢到cpu 的使用权
运行
阻塞
线程因为某种情况暂时停止执行
1. 等待阻塞,线程调用了wait方法,此时线程会进入等待队列,wait方法会丢失锁的所有权,sleep会
2. 同步阻塞,当线程争抢上锁的资源时发生的阻塞
3. 其他阻塞,运行(running)的线程执行Thread.sleep(long ms)或t.join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入可运行(runnable)状态。
死亡
线程优先级
可以通过Thread.currentThread().setPriority(*)设置优先级
取值范围1~10 数字越高优先级越大
优先级高的不一定先执行完
线程的调度
协同式
抢占式
线程池
线程池流程图
核心线程数:最少线程数,最大线程数:无论并发多少允许创建的最大线程数
Executors.newCacheThreadPool()
这种方式没有入参,核心线程数为0个,最大线程数为Integer.maxValue空闲线程60m关闭,使用简单无需参数
Executors.newFixedThreaPool(设置核心线程数及最大线程数)
这种方式可以根据我们服务器的配置来动态设置最大线程数提高硬件利用率
Executors.newSingleThreadPool()
只提供一个线程来对外提供服务
Executors.newScheduledThreadPool(设置核心线程数)
可以来做定时任务
ForkJoinPool.commonPool()
返回值为ForkJoinPool,可以通过ForkJoinPoll.excute来执行继承了RecursiveAction抽象类的任务,来达到一个任务多个线程操作
new ThreadPoolExecutor()
参数
int corePoolSize
核心线程数
int maximumPoolSize
最大线程数
long keepAliveTime
当线程闲置时最大活跃时间
TimeUnit unit
最大活跃时间单位
BlockingQueue<Runnable> workQueue
阻塞队列
无界队列
无界队列是LinkedBlockQueue,使用慎重,当并发量大时所有溢出任务都会丢进这个队列,可能会造成OOM
有界队列
ArrayBlockingQueue
遵循FIFO原则的队列,预先设置好大小
PriorityBlockingQueue
优先级队列,需要传入比较规则
同步队列
SynchronousQueue
不是一个真正的队列,而是一种线程之间移交的机制。要将一个元素放入SynchronousQueue中,必须有另一个线程正在等待接收这个元素。只有在使用无界线程池或者有饱和策略时才建议使用该队列。
ThreadFactory threadFactory
表示线程工厂一般使用默认的
RejectedExecutionHandler handler
表示丢弃策略
AbortPolicy中止策略
当线程已满时抛出异常,异常可以被调用者捕获处理
DiscardPolicy抛弃策略
饱和时不做任何处理,直接丢弃
DiscardOldestPolicy抛弃旧任务策略
饱和时丢弃旧的任务,不能与优先阻塞队列使用
CallerRunsPolicy调用者运行
饱和时将任务丢给调用者执行,所以调用者线程会被阻塞
submit和excute的区别
submit会返回一个future对象可以获取到返回值,如果传入的任务没有返回值那么返回null,而且submit是可以获取任务的异常的
excute没有返回值
线程安全
happen-before
对于两个线程A,B,如果A 发生在 B之前,那么保证A操作完的结果对B是可见的
as-if-serial
对于指令排序,无论如何排序不会影响最后的结果
锁
死锁
什么是死锁
当两个或多个线程互相争抢其他线程所有的互斥资源时,无外力情况下会一直等待
死锁产生的必要条件
互斥条件
争抢的资源只能被一个线程所占有,并不可以被剥夺
请求和保持条件
当一个线程请求占用资源时,另外一个线程保持不释放
不剥夺条件
cpu,主存均属于可剥夺的资源,打印机等是不可被剥夺资源,意思是当一个资源被一个线程所占用时其他线程无法强制获取这个资源
环路等待条件
死锁排查
使用java命令jstack查看线程栈的快照信息
如何避免死锁
当多个线程需要获取相同的一些锁时,尽量保证锁的加锁顺序是相同的
加锁时限:当一个线程获取到锁时给他一个失效时间,感觉不太靠谱
死锁监测
锁的优化
锁的升级
偏向锁
当一个线程访问请求一个锁时如果没有其他线程争抢占用,那么就会加一个偏向锁
轻量级锁
当一个线程请求获取一个锁时发现这个资源已经是偏向锁,此时两个线程开始将markword的信息放入自己操作栈中,生成Lock Record 并通过CAS将锁资源的markword的锁记录指针指向自己,资源的锁记录指针指向谁,谁就拥有了这把锁,其他线程开始自旋
重量级锁
当自旋线程过多或者自旋次数过多时,未抢到锁的线程就会被放入等待队列中,并向操作系统申请锁,然后将资源对象头中的锁记录指针指向操作系统锁,这个时机由jvm管控
锁的消除
jvm执行引擎中有一个即时编译器 JIT,他会在编译阶段通过逃逸分析来分析锁的资源是否会被共享,如果是无用锁就会被直接去除
锁的粗化
直接上代码,类似于这种代码,及时编译器会将锁的力度粗化到for这一层
锁的细化
当我们锁资源时尽量将锁的力度缩小,比如说ConcurrentHshMap对于需要保证线程安全的操作,他只会锁一个桶
synchronize
synchronized与lock的区别
本质上synchronize是一个关键字,Lock是一个接口
锁的释放上,synchronize是当线程执行结束或者线程执行过程出现了异常,都会释放锁,Lock需要自己去释放锁
Synchronize是不可中断的非公平锁,Lock是可以中断的非公平锁或者公平锁
当并发量小时Synchronize性能优于Lock当并发量高时Lock性能依然保持的很好
ReentrantLock
构造器
ReentrantLock()
非公平锁
每当一个线程争抢锁时都会尝试获取,如果获取不到再进入等待队列
ReentrantLock(Boolean fair)
公平锁
直接将线程放入等待队列
原理
继承了AQS抽象类,通过双链表+锁的状态值+CAS来实现
节点等待的四种状态
CANCELLED 值为1
因为超时或某种原因被取消的线程
SIGNAL 值为-1
表示这个Node的继任Node被阻塞了,到时需要通知它
CONDITION 值为-2
表示这个Node在条件队列中,因为等待某个条件而被阻塞
PROPAGATE 值为-3
使用在共享模式头Node有可能处于这种状态, 表示锁的下一次获取可以无条件传播
使用在共享模式头Node有可能处于这种状态, 表示锁的下一次获取可以无条件传播
流程图
ReentrantReadWriteLock
使用场景
当读操作多而修改操作少时使用
实现原理
和ReentrantLock相似,只不过把statusOffset分成两部分,高16位代表读锁状态,低16位带表读锁的状态,读锁是共享的但是有阈值,读写互斥,写写互斥
API
getQueueLength()
获取阻塞队列长度
getReadLockCount()
获取读锁所有者数量
hasQueuedThreads()
获取当前队列是否有正在等待获取锁的线程
reentrantReadWriteLock.readLock().newCondition()
获取线程通信对象
子主题
condition.await();
当前线程等待让出锁的所有权
condition.signal();
唤醒一个等待的线程
Semaphore
主要使用场景是限流,可以通过信号量来控制锁的所有者数量
API
Semaphore sp = new Semaphore(3);
参数为信号量大小
sp.acquire();
请求一个信号量,如果信号量有闲置的就-1,成功获取,否则进入阻塞状态
sp.release();
释放一个信号量,信号量+1,唤醒阻塞线程
CountDownLatch
主要使用场景为保证若干子任务完成后完成其他任务
API
CountDownLatch latch = new CountDownLatch(3);
参数为子任务的数量
latch.countDown();
信号量-1
latch.await();
等待信号量为0时,执行后面逻辑
垃圾回收
算法
标记清除,标记整理,拷贝
JVM调优命令
jps
查看当前所有Java进程
jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]
参数
class (类加载器)
jstat -class pid:显示加载class的数量,及所占空间等信息。
compiler (JIT)
jstat -compiler pid:显示VM实时编译的数量等信息。
gc (GC堆状态)
jstat -gc pid:可以显示gc的信息,查看gc的次数
gccapacity (各区大小)
jstat -gccapacity:可以显示,VM内存中三代(young,old,perm)对象的使用和占用大小
gccause (最近一次GC统计和原因)
jstat -gcnew pid:new对象的信息。
gcnew (新区统计)
jstat -gcnewcapacity pid:new对象的信息及其占用量。
gcnewcapacity (新区大小)
jstat -gcnewcapacity pid:new对象的信息及其占用量。
gcold (老区统计)
jstat -gcold pid:old对象的信息。
gcoldcapacity (老区大小)
jstat -gcoldcapacity pid:old对象的信息及其占用量。
gcpermcapacity (永久区大小)
jstat -gcpermcapacity pid: perm对象的信息及其占用量。
gcutil (GC统计汇总)
jstat -util pid:统计gc信息统计。
printcompilation (HotSpot编译统计)
jstat -printcompilation pid:当前VM执行的信息。
一般用于查看gc日志
jinfo
输出对应名称的参数的具体值。
jmap [option] <pid>
参数
-heap
打印堆信息快照
-histo[:live]
打印所有对象信息,如果加上:live只打印存活对象
-clstats
打印类加载器的信息
-dump:[live]format=b,file=<filename>
将堆快照转储到本地
-finalizerinfo
打印正等候回收的对象的信息.
一般用于查看堆内存快照
jhat
使用这个命令会生成一个HTTP/HTML的服务器,可以通过浏览器分析堆快照,必须先要使用Jmap导出快照
jstack
打印当前线程虚拟机栈信息,并且会智能提示死锁问题
Found one Java-level deadlock:
0 条评论
下一页