一、创建线程的方式
1.继承Thread类,重写该类的run()方法。类
2.实现Runnable接口,并重写该接口的run()方法,该run()方法同样是线程执行体,创建Runnable实现类的实例,并以此实例作为Thread类的target来创建Thread对象,该Thread对象才是真正的线程对象。接口 静态代理
3.使用Callable和Future接口创建线程。具体是创建Callable接口的实现类,并实现call()方法。并使用FutureTask类来包装Callable实现类的对象,且以此FutureTask对象作为Thread对象的target来创建线程。有返回值和异常。JUC包
二、线程的生命周期及五种基本状态
2.1 线程生命周期:新建(new)、就绪(start/yield等)、运行(CPU run)、阻塞(sleep/join等)、死亡(stop/加flag)。
2.2 Thread类和Object的方法
sleep暂停/yield礼让属于类方法;join插队属于对象方法。
2.3 守护线程
用户线程和守护线程(Daemon)。jvm的退出不用等待守护线程执行完成。例:垃圾回收线程。应用场景:jvm退出时,线程能够自动退出。
设置守护线程:t.setDaemon(true) 验证守护线程:t.isDaemon.
2.4 Hook(钩子)线程
jvm退出的时候,钩子线程就会被启动执行。
Runtime.getRuntime().addShutdownHook(new CleanWorkThread());
2.5 常用方法
isAlive()、setName()、getName()、currentThread()类方法。
三、高并发
3.1 并发:同一个对象多个线程同时操作。抢占资源
3.2 线程同步(线程安全):队列与锁 Synchronized
锁机制:锁住对象或Class对象。
3.3 Synchronized方法和Synchronized块 线程安全
synchronized 方法:public synchronized void test(){}。
synchronized 块:synchronized (obj){}。 obj:同步监视器。粒度更小
性能优化:临界值、double checking。
3.4 并发容器
concurrent包:CopyOnWriteArrayList
3.5 死锁
原因:相互不释放资源。
避免:不要在同一个代码块中,同时持有多个对象锁。
3.6 并发协作 线程协作
3.6.1生产者消费者模式
1) 线程通信
3.6.2协作模型之管程法
1)生产者 消费者 缓冲区
2)Object类 wait() 释放锁,notify()/notifyall() 成对出现
3.6.3协作模型之信号灯法
1)生产者 消费者 标志位
3.6 高级主题-定时调度
java.util.Timer
java.util.TimerTask
3.7 任务定时调度框架-quartz
Scheduler:调度器,控制所有的调度
Trigger:触发条件,采用DSL模式
JobDetail:需要处理的任务
Job:执行逻辑
3.8 重排序:Happen-Before
重排序:编译器和CPU会尝试重排指令使得代码更快地允许。目前:提供性能
数据依赖:编译器和处理器在重排序时,会遵守数据依赖性,编译器和处理器不会改变存在数据依赖关系的两个操作的执行顺序。
3.9 volatile修饰
当一个共享变量被volatile修饰时,它会保证修改的值会立即被更新到主存,
当有其他线程需要读取时,它会去内存中读取新值(JMM通过将工作内存的设为失效,以让其直接去读内存)。
volatile变量的内存可见性是基于内存屏障实现的。
1) java内存模型中的可见性、原子性和有序性。
可见性:是指线程之间的可见性,一个线程修改的状态对另一个线程是可见的。Java中volatile、synchronized和final实现可见性。
原子性:synchronized、lock、unlock保证原子性。
有序性:volatile、synchronized保证线程之间操作的有序性。
2) volatile:保证线程间变量的可见性。不能保证原子性。
3) 原理:内存屏障。通过内存屏障可以禁止特定类型处理器的重排序。
4) volatile规则:如果一个线程对volatile变量读,另一个线程对该变量写,那么写操作一定发生在读操作之前。
3.10 dcl单例模式
volatile:保证线程间变量的可见性。不能保证原子性。
1)构造器私有化-->避免外部new构造器
2)提供私有的静态属性-->存储对象的地址
3)提供公共的静态方法-->获取属性
3.11 ThreadLocal 线程的本地存储区域
get/set/initialValue初始化方法。
private static修饰
InheritableThreadLocal:继承上下文环境的数据,拷贝一份给子线程。
3.12 可重入锁实现原理
锁可以延续使用+计数器。
可重入锁:公平锁和不公平锁。公平锁:等待时间长的先获得锁。
JUC包:ReentrantLock.
3.13 CAS原子操作 Compare and swap 比较并交换。
悲观锁:synchronized关键字、lock接口。
乐观锁:CAS:属于硬件级的操作(利用CPU的CAS指令),是乐观锁的一种实现。效率高
JUC(java.util.concurrent)中AtomicXxx类:AtomicInteger.decrementAndGet()。
四、多线程小结
4.1 推导lambda简化线程 拉姆达
4.2 在并发编程中,比较常用的是使用synchronized关键字和Lock接口同步,或者volatile关键字,来确保多线程下的有序性。