1、基本概念
1.1 线程调用的随机性
1.2 线程的5种状态
线程通常都有5种状态:创建、就绪、运行、阻塞和死亡。
1、创建状态Create:new语句创建的线程对象处于新建状态,此时它和其他java对象一样,仅被分配了内存,没有调用该对象的start()方法之前,这时线程处于创建状态。
等待或睡眠中回来之后,也会处于就绪状态。
3、运行状态Running:线程调度程序将处于就绪状态的线程设置为当前线程,此时线程就进入运行状态,开始运行run函数当中的代码。处于这个状态的线程占用CPU,执行程序代码。在并发运行环境中,如果计算机只有一个CPU,那么任何时刻只会有一个线程处于这个状态。 注意: 只有处于就绪状态的线程才有机会转到运行状态。
4、阻塞状态Blocked:阻塞状态是指线程正在运行的时候,因为某些原因放弃CPU,暂时停止运行。当线程处于阻塞状态时,Java虚拟机不会给线程分配CPU,直到线程重新进入就绪状态,它才会有机会获得运行状态。
阻塞状态分为三种:
1)、等待阻塞:运行的线程执行wait()方法,JVM会把该线程放入等待池中。
2)、同步阻塞:运行的线程在获取对象同步锁时,若该同步锁被别的线程占用,则JVM会把线程放入锁池中。
Sleep()方法,或者发出I/O请求时,JVM会把线程设为阻塞状态。当Sleep()状态超时、或者I/O处理完毕时,线程重新转入就绪状态。
必须要注意,A线程和B线程中涉及同步方法f,C线程中不涉及同步方法f, A线程获得锁后,B线程在此过程中不会执行方法f, A线程、B线程与C线程会按照CPU线程调度切换执行; A线程释放锁(执行完F方法,后面不再执行F方法)后,B线程与C线程与A线程会按照CPU线程调度切换执行;
所以,锁对线程中正要执行的同步方法的继续有影响,但不影响与同步方法无关的线程的执行;即锁只会引起同步阻塞。 | |||
| 被调用后线程状态 | 线程持锁状态(线程中的同步方法) | |
sleep() | 当前线程进入阻塞状态 | 当前线程不会释放同步锁(同步方法被锁在当前线程),也就是说即便其它线程处于可运行状态,但是由于缺乏锁,其它线程会在相应的同步方法处无法继续执行下去,必须等锁 | |
wait()/suspend() | 当前线程进入等待阻塞状态 | 当前线程释放同步锁(同步方法在当前线程中被中止执行),即便是该线程被notify唤醒进入就绪状态下,也无法立即继续执行该同步方法,任然需要等锁,直到获得同步锁后,该线程才会继续执行被中断的同步方法。 | 当在对象上调用wait()方法时,执行该代码的线程立即放弃它在对象上的锁。 然而调用notify()时,并不意味着这时线程会放弃其锁。如果线程任然在完成同步代码,则线程在移出之前不会放弃锁。因此,只要调用notify()并不意味着这时该锁变得可用,只是说明被wait()阻塞的线程进入了就绪状态,是否取得锁还不一定。 |
yield() | 当前线程由运行状态进入就绪状态 | 当前线程不会释放同步锁 | yield不能控制具体的交出CPU的时间,另外,yield方法只能让拥有相同优先级的线程有获取CPU执行时间的机会 |
join() | 当前线程进入等待阻塞状态 | | 它结束的条件是:1)等待时间到;2)目标线程已经run完 |
5)、死亡状态Dead:如果一个线程的run方法 执行结束或者调用stop方法后,该线程就会死亡。对于已经死亡的线程,无法再使用start方法令其进入就绪。