1.使用线程方式
1.1 Runnable接口
1.2 Thread类(本质上实现了Runnable)
1.3 Callable/Future
1.4 ThreadPoll(推荐使用)
2.线程使用场景
2.1 文件跑批
2.2 收益/对账 文件生成
2.3 BIO模型优化
Socket socket = Socket.accept();
new Thread(new Hander(socket)).start();
3.线程的生命周期
NEW
线程初始化状态
RUNNABLE
线程可运行状态
BLOCKED
锁等待状态
a/b两个线程执行同步代码块时,
当a线程获得了锁
此时b线程访问同步代码块,此时b线程状态为:BLOCKED
WAITING
等待状态
wait/join/LockSupport.pack
TIMED_WAITING
带有超时时间的等待状态
wait/join/LockSupport.pack/sleep
TERMINATED
4.线程启动为什么是start?
通过 start0方法 调起 JVM_Start_Thread 方法来启动线程
5.线程的终止
//jdk原生方法 将OS_Thread中 isInterrupted 设为1
//interrupt0()--->JVM_Interrupt
1.Thread.interrupt()
2.Thread.stop() 等失效方法不推荐
6.阻塞线程是否可以终止?
阻塞线程不可以终止,会抛出 InterruptedException 异常,
抛出该异常后,OS_Thread中 isInterrupted变量将复位,变为初始值0
通知该线程处于阻塞中,无法终止
调用方需根据实际需要,自行处理
7.线程安全/数据同步
当多个线程共同修改一个对象的成员变量或一个类的静态变量,
就涉及到了所谓的"线程安全/数据同步,线程安全其实就是避免或防止多个线程间的数据脏读
个人认为处理线程安全的最好方案为避免线程同步,使用无状态对象
如果无法避免使用有状态对象或多个线程修改摸一个类的静态变量就需要使用 synchronized
8.线程锁synchronized
synchronized的特性为在作用域内 [锁共享] 与 [锁互斥]
synchronized 的使用尽量缩小使用范围,这样有利于提高效率
使用多线程就是为了并行执行任务提高效率,如果synchronized锁的范围过大或实际
执行过程中是线性执行,失去了使用多线程的意义
synchronized分为类锁和对象锁
类锁作用在类上,锁的作用域为java类 (修饰实例方法/代码块)
对象锁作用在类的某一个对象上,不同对象之间的锁相互不影响(修饰静态方法/代码块)
8 synchronized在JVM中存储
9 JVM中锁的级别
无锁->偏向锁(一般关闭)->轻量级锁->重量级锁(真正的锁)
synchronized在JDK1.6之前属于重量级锁
10synchronized的触发机制/锁升级
假设存在一个加锁方法
① 当有且只有一个线程访问改带锁方法时,使用的是【偏向锁】采用CAS原子操作
② 当多个线程前后交替访问带锁方法时,【偏向锁】升级为【轻量级锁】
轻量级锁采用"自旋"尝试,一定时间内"自旋"没有成功,升级失败将进行阻塞
(锁膨胀为重量级锁)
自旋会占用CUP资源
自旋次数 可以 通过 preBlockSpin 进行设置
也可以已使用自适应(当CUP使用率达到阈值,自动停止)
③ 当多个线程并行访问带锁方法时,此时放生阻塞,没有获得锁的线程被阻塞变为BLOCKED状态
11 重量级锁切换过程
12 wait /notify/notifyall 属于线程通信机制
wait
a .阻塞当前线程
b.当前线程释放锁资源
notify
a.唤醒当前被阻塞线程
b.占用锁资源
notifyall
唤醒当前锁所有线程,被唤醒线程再次竞争锁