多线程基础(二)线程状态

系列目录

线程状态

  • 新建
  • 就绪
  • 运行
  • 死亡
  • 阻塞
  • 等待
    注:可将阻塞与等待归为一类。

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.阻塞

在运行时失去处理机,且缺少可以执行的条件。

【运行与阻塞的转换】

  • 运行进入阻塞:
  1. 调用sleep(),自主放弃处理机。
  2. 等待IO操作。
  3. 试图获得一个锁(同步监视器),但该锁被其他线程占有。
  4. 系统在等待某个通知(notify)。
  5. 调用了线程的suspend(挂起)方法//容易产生死锁,慎用。
  6. 调用了join方法。
  • 阻塞进入就绪:
    对应于:12345(resume)6join方法完成

5.死亡

进入死亡的方式:

  1. run方法或call方法执行完毕
  2. 线程抛出一个未捕获的异常或者方法
  3. 直接调用stop//容易产生死锁,慎用

【关系图】

【辨别】

  1. sleep() 和 wait() 区别:
    sleep() :可以指定时间,当程序执行到sleep方法时,当前线程在指定时间范围内时不能抢资源;
    不会释放锁资源;定义在Thread中。
    wait() :当程序执行到wait方法时,当前线程进入到等待状态,
    只有通过notify或者notifyAll方法唤醒才会继续执行;会释放锁资源;定义在Object类中。

  2. 同步和异步:
    同步:只有一个线程可以执行,效率低
    异步:多个线程可以交替执行,效率高

原文地址:https://www.cnblogs.com/juzhuxiaozhu/p/12761597.html