线程状态:
![6262743-0ad82e79f0c6d498.png](https://i-blog.csdnimg.cn/blog_migrate/258cec1409734118d5eb6960f1854941.png)
![6262743-fe65380885a21252.png](https://i-blog.csdnimg.cn/blog_migrate/7bec2cb1bb48cdee9b57b0b24fc12b29.png)
- 新建:new了以后新建了线程对象
- 等待:after new,before start(),在new完了以后,在调用start方法之前
- 就绪:start()被调用之前,但是还没有或得cpu的使用权之前
- 运行状态:当前线程正在占用CPU,执行代码。(只有处于就绪状态的线程才有机会进入运行状态)
- 阻塞状态:线程放弃了cpu,由运行状态进入了阻塞状态,在下次获取cpu的时候,会从阻塞状态进入运行状态
- 死亡状态:线程执行完了,或者线程异常终止了,这个线程就死亡了。
线程的几个方法
首先需要分清楚两个东西,一个是cpu的使用权,还有一个是锁。
CPU使用权是线程运行的时候需要考虑到的事情,多线程的同时运行其实并不是真正的,而是cpu轮流的运行,线程想要运行,需要先获取到cpu的使用权,然后才会执行。比如cpu现在在运行线程a,过一会儿线程b拿到了cpu的使用权,线程b开始运行,这个时候线程a就会停下来。
还有一个概念是锁,一个对象如果设置了锁,是不允许多个线程同时操作的,一个线程释放了锁,另一个线程拿到了锁才可以操作这个对象。
sleep方法
sleep让线程让出cpu的使用权,让出去以后究竟是谁拿到cpu的使用权就不归他管了。sleep里面的时间参数如果到了,这个线程会再次进入就绪状态,需要注意的是进入的是 就绪状态,但是并不一定会马上获取到cpu的使用权,也就是说这个时间参数设置的时间过去以后,这个线程可能会马上继续执行,也可能不是。还有这个sleep方法在让出cpu使用权的时候却不会释放锁。如果当前线程拿到一个锁,然后sleep了,另一个线程也需要操作这个锁住的对象的话,就不行了,因为另一个线程是拿不到锁的。
总结一下就是:
- sleep并不会让cpu卡在那里,它会让出cpu的使用权
- sleep不会把拿到的锁释放出去
- sleep结束以后,线程进入就绪状态,而不是运行状态
join方法
join方法是在本线程中用其他线程的对象来调用的,举个例子当前运行的t1线程,我需要在t1线程里调用t2.join()。join 的意思是把当前线程t1的cpu使用权让出去,然后把使用权交给t2。如果不指定参数,t2将一直运行,直到运行结束。还可以指定时间参数,可以让t2在一定时间内一直获取到cpu使用权。另外join方法实惠释放锁的。
再总结一下
- join让出了cpu使用权,并且指定了把cpu使用权给了哪个线程
- join释放了锁
- join之后也是进入到就绪状态
yield方法
这个就比较简单了,就是让出cpu使用权,线程进入到就绪状态。这个和sleep一样并不会释放锁
wait方法
这个让出cpu的使用权,释放了锁。然后线程进入到等待池中,在这个池中的话,就一直等,直到被别的线程调用notify唤醒,才会进入到就绪状态。
notify和notifyAll
唤醒待在等待池中的线程,notify是随机唤醒一个,notifyAll是唤醒所有。
t1.interrupt();
这个是给t1线程只一个标志位,但是并不会有实际的作用,通常需要在t1代码中手动判断这个标志,比如:
通过t1.interrupt();方法把标志为置为true,但是我还没有找到把标志位置为false的方法,好像就是没有。
while(!isInterrupted()) {
System.out.println(isInterrupted()+"=== "+i);
i++;
}