java高并发基础概念
Java高并发基础
线程安全:一个类被多个线程同时调用时,且不需要外部额外同步和协同的情况下,仍然保持内部数据正确且表现正确的形态
不可变的对象一定是线程安全的
如final修饰的不可变量, string integer等
Enum枚举类
在用final修饰list时list中是可以添加数据的,只是用来保证内存地址值不会被覆盖
线程安全类的任意方法操作都是不会使该对象的数据处于不一致或数据污染的情况
对于单独的访问类的方法,是线程安全,但是对于某些复合操作需要外部同步
线程对立类是不管是否使用了外部同步都不能在并发使用时保证其安全的类
同步的概念:发送一个请求,等待返回再执行下一个请求
异步的概念:发送一个请求,不用等待返回可直接执行下一个程序
同步和异步关注点为得到结果的方式
同步 |
异步 |
|
优势 |
1、可以拿到实时结果进行处理,上下文信息始终在一个代码块,代码处理上更加方便直观 2、对错误和异常处理可以做到实时 |
1、不影响主流程的执行,降低响应时间,提高应用的性能和效率 2、及时释放系统资源,如线程占用,让系统去做更多有价值的事 |
劣势 |
1、耗时的接口响应会影响整个流程的性能 |
1、为了保障数据最终一致性,需要对账系统去做好监控和保障 2、需要更多异步任务去补偿系统间的数据一致性 |
阻塞:调用结果返回前,当前线程会被挂起,调用线程只有在得到结果之后才会返回。
非阻塞:指在不能立刻得到返回结果之前,该调用不会阻塞当前线程,而回直接返回
阻塞和非阻塞关注点在调用结果时的状态
单线程:
程序在执行过程中始终只有一个线程在运行,后面的代码必须等待前面的代码执行完毕后才可执行
多线程:
程序由多个线程构成,方法内各代码块的执行顺序不确定
并发:
逻辑上的同时处理,能处理多个时间,但是时间一个较短时间分给不同事件来处理
并行:
物理或实际上的同时处理,在同一时间同时处理多个事情
线程的多个状态:
线程间状态切换图
线程的部分方法
Thread.yield()
线程让步,使用了这个方法,当前线程就会退出CPU时间片,让其他线程或当前线程使用CPU时间篇执行
Thread.sleep()
线程休眠,主动让出当前CPU时间,在指定时间过后,CPU会返回继续执行该线程。sleep方法不会释放当前所持有的锁,也就是在休眠时其他代码也无法调用此线程
Thread.join()
等待该线程死亡/终止,当前线程会等待调用该方法的线程执行完毕后才能继续执行
Object.wait()
Object类的方法,调用前必须拥有对象锁,例如在synchronized代码块内,调用wait方法后,对象锁会释放,线程进入WAITING等待状态
线程死锁
死锁是指两个或两个以上的线程在执行过程中由于竞争资源或由于彼此通信而造成的一种阻塞现象,若无外力作用他们讲无法推进下去,此时系统处于死锁状态,会系统产生死锁
这些相互等待的进程称为死锁进程
避免和处理死锁问题
- 不使用锁,不使用2把及以上的锁
- 必须使用2把及以上锁的时候,确保在整个应用程序中对获取锁的顺序是一致的
- 尝试获取具有超时释放的锁,例如Lock中的tryLock来获取锁
- 当发生了Java-level的锁时,重启程序来干掉进程/线程
定位死锁问题
- jps
列举正在运行的虚拟机进程并显示虚拟机执行的主类以及这些进程的唯一ID(PID)
- jstack
用于JVM当前时刻的线程快照,得到JVM当前每一条线程正在执行的堆栈信息,定位线程长时间卡顿问题,如死锁、死循环等问题