@see
https://juejin.im/entry/57339fe82e958a0066bf284f
http://www.infoq.com/cn/articles/java-interrupt-mechanism
Java线程基本概念
进程是资源分配的基本单位,线程是调度的基本单位。进程包含线程,线程共用进程的资源。线程中存在于进程中,每个进程都至少一个线程。
守护线程
线程分两种—用户线程、守护线程。The Java Virtual Machine exits when the only threads running are all daemon threads.当只剩下守护线程时,JVM将会退出。当有任意用户线程存在时JVM都不会退出。无其他区别。
线程状态转换:图请谷歌或自行脑补
各种状态一目了然,值得一提的是"Blocked"这个状态:
1、调用join()和sleep()方法,sleep()时间结束或被打断,join()中断,IO完成都会回到Runnable状态,等待JVM的调度。
2、调用wait(),使该线程处于等待池(wait blocked pool),直到notify()/notifyAll(),线程被唤醒被放到锁定池(lock blocked pool ),释放同步锁使线程回到可运行状态(Runnable)
3、对Running状态的线程加同步锁(Synchronized)使其进入(lock blocked pool ),同步锁被释放进入可运行状态(Runnable)。
线程状态:
NEW - RUNNABLE - BLOCKED - WAITING - TIMED_WAITING - TERMINATED
wait(time) / sleep(time):RUNNABLE -> TIMED_WAITING
wait/notify
synchronized(obj) { //Thread t1 got the lock first obj.wait(); // t1 going to wait, release the lock }synchronized(obj) { //Thread t2 got the lock after t1 release the lock, now, t1 State: WAITING obj.notify(); //notify t1, t1 State: BLOCKED do something... }
1、场景:t1 先获取锁,t2在t1释放锁后,获取锁
2、t1: RUNNABLE -> WAITING 进入等待队列, notify/notifyAll,WAITING -> BLOCKED 进入同步队列,注意是在notify()之后,WAITING -> BLOCKED 状态就发生变化,不用到synchronized的作用域之后 t1: WAITING -> BLOCKED,仅仅是进入同步队列,当前持有锁的线程t2并没有释放锁,要等到synchronized的作用域之后(monitor exit),才能参与锁的竞争
源码分析
1、start
- public synchronized void start() 同步方法。
2、sleep
- public static native void sleep(long millis) throws InterruptedException 静态本地方法。使当前线程休眠一定时间,但是休眠期间不释放持有锁。 - public static void sleep(long millis, int nanos) throws InterruptedException 对nanos判断,实际调用的上面的sleep方法。
3、join
- public final synchronized void join(long millis) throws InterruptedException
final且同步方法。join方法是等待该线程执行,直到超时或者终止,可以作为线程通信的一种方式:A线程调用B线程的join(阻塞),等待B完成后再往下执行。
原理:wait()
public final synchronized void join(long millis)throws InterruptedException { ... if (millis == 0) { while (isAlive()) { wait(0); } } ...}
示例: { // current Thread -a running...// Thread b = new Thread(); b.join();}
利用wait方法实现:在a线程中调用b.join,a先获取b的对象锁,当b仍然存活,则b.wait(),即阻塞当前a线程,直至被唤醒。
唤醒后继续判断b是否存活,若b仍然存活,则继续wait。否则,表明b已经执行完,a线程继续往下执行。
4、yield
@see http://www.importnew.com/14958.html
理论上,yield意味着放手,放弃,投降。一个调用yield()方法的线程告诉虚拟机它乐意让其他线程占用自己的位置。这表明该线程没有在做一些紧急的事情。注意,这仅是一个暗示,并不能保证不会产生任何影响。yield 可以直接用 Thread 类调用,yield 让出 CPU 执行权给同等级的线程,如果没有相同级别的线程在等待 CPU 的执行权,则该线程继续执行。
5、exit
- private void exit() 私有方法,由系统调用,用于线程真正退出之前进行一些清理操作。group、target、threadLocals 等都被赋值null,释放所有引用。
6、stop
不推荐使用,已废弃。
stop和中断:它们的区别在哪里?最重要的就是中断需要程序自己去检测然后做相应的处理。
被弃用的原因:@deprecated This method is inherently unsafe. Stopping a thread withThread.stop causes it to unlock all of the monitors that ithas locked (as a natural consequence of the uncheckedThreadDeathexception propagating up the stack). Ifany of the objects previously protected by these monitors were inan inconsistent state, the damaged objects become visible toother threads, potentially resulting in arbitrary behavior.
stop方法本质上就是不安全的。stop会释放所有已经持有锁的监视器,这将导致对象状态不一致,可能会产生任意不受控制的结果。 例如,线程t1 synchronised(obj){ accountA + 100, accountB - 100 } 假设在accountA、accountB之间调用了t1.stop,此时释放锁,则原子性就被破坏了,导致对象处于不一致状态。
网友评论