Java基础-线程 (二)
线程的6种状态(生命周期):
1.NEW:创建一个线程对象new Thread(),没有调用start()方法,仅分配线程所需的资源。
2.RUNNABLE:准备就绪 或 运行中。
3.BLOCKED:表示线程阻塞于锁。场景:调用Thread.sleep()阻塞、等待IO操作或者某个锁、等待一定的触发条件。一次阻塞就将会进行一次上下文切换,而上下文切换是很耗费性能的(上下文切换3~5ms,执行一条命令0.6ns)。
4.WAITING:进入该状态的线程需要等待其他线程做出一些特定动作,场景:线程可能因为调用了Object.wait()或Thread.join()。
5.TIMED_WAITING:在指定等待时间后等待线程的线程状态,场景:可能因为调用Thread.sleep()或加上超时值来调用Object.wait()或Thread.join()
6.TERMINATED:线程已运行完毕。它的run()方法已正常结束或通过抛出异常而结束。
线程饥饿:指线程的优先级太低,总是拿不到执行权。
死锁:在两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象
发生场景:多使用者(M>=2),多被使用者(N>=2),且N<=M时才会发生这种情况。
举个栗子:
张三和李四在2个小黑屋。由于太黑了他们都想照亮房间,我们指定照亮房间的操作必须要持有打火机和蜡烛,才能点燃照亮。由于可能会发生这种情况。张三拿到了打火机,李四拿到了蜡烛。他们再拿另外一个必需品的时候总是拿不到,但是手里的资源又不放手。这样就产生了死锁。危害导致2个线程都挂在那不工作了,但是他们还一直处于运行状态。一般我们只能重启程序解决。
总结:死锁一定是处于:请求保持,且不剥夺的条件下,处于环路等待的状态。
解决:(下面描述的锁,其实就是被使用者)
1.内部通过顺序比较,确定拿锁的顺序。通过协议避免。
2.采用尝试拿锁的顺序。(如A使用者在拿到N的时候尝试获取M,获取不到就释放N:(活锁)这种情况会导致互相谦让最终都拿不到或者执行多次才拿到的请,一般我们会使用线程休眠错开拿锁时间,来解决这个现象)
ThreadLocal是什么?
ThreadLocal字面意思就是线程的本地变量。可以理解他是线程私有的一个本地变量副本。主要作用是实现了变量的线程隔离。可以理解它存储这本线程的局部变量。
值互不相影响为什么会这样,看一下源码:
threaLocal.set()拿到当前线程的ThreadLocalMap,我们看一下Thread类和Thread类的getMap(t)方法。
ThreaLocal类中的getMap() Thread类中所以map.set方法就是拿到当前线程的ThreadLocalMap,然后去set().
ThreadLocalMap是一个数组 以threadLocal变量为键,value为值总结:ThreadLocal 就是线程的本地存储,他存储在线程内部的ThreadLocalMap数组中。可以看做参数的工作副本,起到线程隔离的作用。