文章目录
进程与线程的区别
线程状态及转换
什么是线程挂起(非可执行的状态)
线程的创建方法
一般使用匿名内部类实现或者使用labmda表达式
什么是守护线程
区别于非守护线程,一旦没有非守护线程,守护线程就会自动结束自己的生命周期,此时就会关闭jvm进程
什么是死锁和如何防止死锁
并发编程的三个重要特性
CAS原理(无锁)
原子操作类
CAS实现原子操作的三大问题
synchronized关键字(不透明锁,方法/代码块)
synchronized 关键字最主要的三种使用方式:
synchronized 关键字底层原理属于 JVM 层面
volatile关键字(读写屏障,变量)
JMM(java内存模型)
volatile解决数据不一致问题
volatile的读写屏障
synchronized 关键字和 volatile 关键字的区别
Lock锁(类)—AQS原理AbstractQueuedSynchronizer
AQS资源共享方式(进行分类不同的阻塞同步锁)
ReentrantLock(独占方式)–(公平锁与非公平锁的区别)
ReentrantReadWriteLock(两种资源共享方式)
只有读读能共享,读写互斥,写写互斥:
CountDownLatch倒计时器(多线程相互等待全部完成)–(应用场景)
CompletableFuture的异步并行与等待
Semaphore(限流器–限制共享资源线程的数量)
Semaphore(信号量)可以指定多个线程同时访问某个资源。实际相当于刚开始permits数量的上限线程同时访问某个资源,后面最多只有permits个线程可以使用这个许可证,其余的线程必须等待由许可的线程release才有机会获得许可!!(所以semaphore可以用作限流器)
可以发现countdownLatch只能减少至0,没有释放的操作。但是semphore有acquire占用state,也可以release释放资源,显示了state的复用的功能
Synchronized和Lock之间的区别
并发容器(JUC包下)
ConcurrentHashMap(对比HashMap,HashTable)
CopyOnWriteArrayList(读读共享)
ConcurrentLinkedQueue(CAS非阻塞队列)
ConcurrentSkipListMap(跳表)
不知道是维护了多级的指针还是维护了多个链表
Threadlocal(本地线程局部变量)
TreadLocal的set方法:先拿到自己线程的ThreadLocalMap,然后将这个Threadlocal作为键,set进入的参数value作为值(get方法是类似的思想)
经典的例子
ThreadLocal的内存泄漏问题
线程池(框架Executor)
线程池的状态
创建线程池的方式 (Excutors静态方法 | ThreadPollExcutor的构造函数)
线程池中执行 execute()方法和 submit()方法的区别是什么呢?
ThreadPoolExecutor 类及其构造方法分析
构造方法参数分析
具体的线程分配情况–执行的原理
任务队列都满时,才会启用急救线程
线程用完时的拒绝策略
一个线程池执行任务的demo
step1:首先实现一个自己的Runnable(Callbable)接口,来实现自己执行任务的方法
step2: 使用ThreadPoolExecutor创建自定义的线程池,实际上就是调用它的"构造方法",创建"自己的参数的线程池"
step3: 使用“线程池的execute(myrunnable)”来提交执行任务(实现的myCallable使用submit提交任务,同时有future对象返回用于获取执行的结果)
一些补充
指令重排序相关
as-if-serial语义(编译器优化重排序)
happens-before的定义(内存系统重排序)
Synchronized锁升级
偏向锁(减少CAS)
判断偏向锁的标志位是否为1,如果不为1,此时先尝试CAS轻量级锁
轻量级锁(Object:CAS自旋竞争)
为每个线程创建一个锁记录对象(存放在本线程的栈帧中,锁重入就会再创建一个锁记录对象放在栈帧中),将锁记录对象的object reference指向锁定对象 && 将锁地址与锁定对象的Markword的hashcode进行CAS尝试交换。
锁膨胀(CAS自旋失败,Object申请Monitor)
重量级锁(Monitor–Owner&EntryList Blocked)
注意这张图:老式的直接重量级锁的情况,具体还是按照锁膨胀的那个为准,主要学习一下monitor的结构monitor的结构:(owner指向当前占用object对象的线程,entryList表示阻塞队列—后续锁释放会抢锁,waitSet等待队列–主动释放锁且需要唤醒才能加入阻塞队列进行抢锁)
owner重量级锁的线程wait()的原理
注意:wait和notify的方法属于object对象的!!(针对这个锁定对象object可以调用wait和notify分别用来对应waitset中的某个线程)
Object 类是一个特殊的类,是所有类的父类
public final native Class<?> getClass()//native方法,用于返回当前运行时对象的Class对象,使用了final关键字修饰,故不允许子类重写。
public native int hashCode() //native方法,用于返回对象的哈希码,主要使用在哈希表中,比如JDK中的HashMap。
public boolean equals(Object obj)//用于比较2个对象的内存地址是否相等,String类对该方法进行了重写用户比较字符串的值是否相等。
protected native Object clone() throws CloneNotSupportedException//naitive方法,用于创建并返回当前对象的一份拷贝。一般情况下,对于任何对象 x,表达式 x.clone() != x 为true,x.clone().getClass() == x.getClass() 为true。Object本身没有实现Cloneable接口,所以不重写clone方法并且进行调用的话会发生CloneNotSupportedException异常。
public String toString()//返回类的名字@实例的哈希码的16进制的字符串。建议Object所有的子类都重写这个方法。
//native方法,并且不能重写。唤醒一个在此对象监视器上等待的线程(监视器相当于就是锁的概念)。如果有多个线程在等待只会任意唤醒一个。
public final native void notify()
//native方法,并且不能重写。跟notify一样,唯一的区别就是会唤醒在此对象监视器上等待的所有线程,而不是一个线程。
public final native void notifyAll()
//native方法,并且不能重写。暂停线程的执行。注意:sleep方法没有释放锁,而wait方法释放了锁 。timeout是等待时间。
public final native void wait(long timeout) throws InterruptedException
//多了nanos参数,这个参数表示额外时间(以毫微秒为单位,范围是 0-999999)。 所以超时的时间还需要加上nanos毫秒。
public final void wait(long timeout, int nanos) throws InterruptedException
//跟之前的2个wait方法一样,只不过该方法一直等待,没有超时时间这个概念
public final void wait() throws InterruptedException
protected void finalize() throws Throwable {
}//实例被垃圾回收器回收的时候触发的操作
举个例子:
public class WaitNotify {
public static void main(String[] args)