多线程基础(二)线程状态
系列目录
线程状态
- 新建
- 就绪
- 运行
- 死亡
- 阻塞
- 等待
注:可将阻塞与等待归为一类。
1.新建
new出对象后即为新建状态。此时jVM仅为其分配内存并初始化成员变量未表现出任何线程的动态特征。
2.就绪
调用start方法后即为就绪状态。jVM为其创建方法调用栈和程序计数器。
此时线程并未执行,仅表示该线程可以执行了,至于何时执行要看JVM的决策。
- 关于 start() 和 run()
调用start方法来启动线程,系统会把其中的run方法作为线程执行体来执行;
若直接调用run方法,则run方法会被立即执行,且作为一个普通的方法,失去线程的特性。
而且在run方法返回之前,其他线程不能并发执行。
package myThread;
/**
* 直接调run()方法,Thread中的getName()返回的是该对象名称
* 而非当前线程的名称
*
* 在此案例中,main是线程名称,Thread是对象名称
*
*/
public class InvokeRun extends Thread{
private int i;
@Override
public void run(){
for(;i<100;i++){
//System.out.println(getName()+" "+i);
System.out.println(Thread.currentThread().getName()+" "+i);
}
}
public static void main(String[] args) {
for(int i = 0;i<100;i++){
System.out.println(Thread.currentThread().getName()+" "+i);
if(i==20){
new InvokeRun().run();
new InvokeRun().run();
}
}
}
}
3.运行
就绪状态的线程获得处理机,即处于运行状态。
4.阻塞
在运行时失去处理机,且缺少可以执行的条件。
【运行与阻塞的转换】
- 运行进入阻塞:
- 调用sleep(),自主放弃处理机。
- 等待IO操作。
- 试图获得一个锁(同步监视器),但该锁被其他线程占有。
- 系统在等待某个通知(notify)。
- 调用了线程的suspend(挂起)方法//容易产生死锁,慎用。
- 调用了join方法。
- 阻塞进入就绪:
对应于:1\2\3\4\5(resume)\6join方法完成
5.死亡
进入死亡的方式:
- run方法或call方法执行完毕
- 线程抛出一个未捕获的异常或者方法
- 直接调用stop//容易产生死锁,慎用
【关系图】
【辨别】
-
sleep() 和 wait() 区别:
sleep() :可以指定时间,当程序执行到sleep方法时,当前线程在指定时间范围内时不能抢资源;
不会释放锁资源;定义在Thread中。
wait() :当程序执行到wait方法时,当前线程进入到等待状态,
只有通过notify或者notifyAll方法唤醒才会继续执行;会释放锁资源;定义在Object类中。 -
同步和异步:
同步:只有一个线程可以执行,效率低
异步:多个线程可以交替执行,效率高