[Java][华为云Java编程创造营][学习笔记][第三阶段][05_Java多线程实战][02_线程生命周期和状态]

举报
John2021 发表于 2021/12/17 06:08:00 2021/12/17
【摘要】 2.1,线程的生命周期和状态在线程的生命周期中,它要经过新建(New),就绪(Runnable),运行(Running),阻塞(Blocked)和死亡(Dead)5种状态。当线程启动以后,它不可能一直”霸占“着CPU独自运行,所以CPU需要在多条线程之间切换,于是线程状态也会多次在运行、阻塞之间切换。线程的生命周期五个阶段:新建状态,当程序使用new关键字创建了一个线程之后,该线程就处于新...

2.1,线程的生命周期和状态

  • 在线程的生命周期中,它要经过新建(New),就绪(Runnable),运行(Running),阻塞(Blocked)和死亡(Dead)5种状态。

  • 当线程启动以后,它不可能一直”霸占“着CPU独自运行,所以CPU需要在多条线程之间切换,于是线程状态也会多次在运行、阻塞之间切换。

  • 线程的生命周期五个阶段:

    1. 新建状态,当程序使用new关键字创建了一个线程之后,该线程就处于新建状态,此时仅由JVM为其分配内存,并初始化其成员变量的值。
    2. 就绪状态,当线程对象调用了start()方法之后,该线程处于就绪状态。JVM会为其创建方法调用栈和程序计数器,等待调度运行。
    3. 运行状态,如果处于就绪状态的线程获得了CPU,开始执行run()方法的线程执行体,则该线程处于运行状态。
    4. 阻塞状态,当处于运行状态的线程失去所占用资源之后,便进入阻塞状态。
    5. 在线程的生命周期当中,线程的各种状态的转换过程。

2.2,线程的睡眠

  • 线程休眠的方法是Thread.sleep(long millis)
  • 线程休眠的目的是使线程让出CPU的最简单的做法之一,线程休眠的时候,会将CPU资源交给其他线程,以便能轮换执行,当休眠一定时间后,线程会苏醒,进入准备状态等待执行。
  • 简单说,哪个线程调用sleep方法,就休眠哪个线程。
class UserThread extends Thread
{
    public void run()
    {
        System.out.println(Thread.currentThread().getName() + ",A");
        try
        {
            Thread.sleep(2000);
        } catch (InterruptedException e)
        {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + ",B");
    }
}

public class Demo19
{
    public static void main(String[] args)
    {
        /*
         * 线程的执行顺序不能精确控制,哪个线程执行sleep方法,就休眠,一定让出执行权给其他线程
         * */
        UserThread u1 = new UserThread();
        UserThread u2 = new UserThread();
        u1.start();
        u2.start();
        /*
        * 输出结果
        *   Thread-0,A
            Thread-1,A
            Thread-0,B
            Thread-1,B
        * */
    }
}

2.3,线程的让步

  • yield()的作用是让步。它能让当前线程由"运行状态"进入"就绪状态",从而让其他具有相同优先级的等待线程获取执行权。
  • 但是,并不能保证在当前线程调用yield()之后,其它具有相同优先级的线程就一定能获得执行权;也有可能是当前线程又进入到"运行状态"继续运行。
  • 简单地说,就是哪个线程执行yield方法,就是礼让。
class UserThread extends Thread
{
    public void run()
    {
        System.out.println(Thread.currentThread().getName() + ",A");
        Thread.yield();
        System.out.println(Thread.currentThread().getName() + ",B");
    }
}

public class Demo20
{
    public static void main(String[] args)
    {
        /*
         * 线程yield让步,执行权可能让给其它线程,也可能让给自己,让步可以理解成礼让
         * */
        UserThread u1 = new UserThread();
        UserThread u2 = new UserThread();
        u1.start();
        u2.start();
        /*
        * 输出结果
        *   Thread-0,A
            Thread-0,B
            Thread-1,A
            Thread-1,B
        * */
    }
}

2.4,线程的合并

  • 线程的合并的作用就是将几个并行线程合并为一个单线程执行。
  • 当一个线程必须等待另一个线程执行完毕才能执行时可以使用join方法。
class UserThread extends Thread
{
    public void run()
    {
        for (int i = 0; i < 10; i++)
        {
            System.out.println("线程1第" + i + "次执行!");
        }
    }
}

public class Demo21
{
    public static void main(String[] args)
    {
        UserThread ut = new UserThread();
        ut.start();
        for (int i = 0; i < 20; i++)
        {
            System.out.println("主线程第" + i + "次执行");
            try
            {
                ut.join();
            } catch (InterruptedException e)
            {
                e.printStackTrace();
            }
        }
        /*
        * 输出结果
        *   主线程第0次执行
            线程1第0次执行!
            线程1第1次执行!
            线程1第2次执行!
            线程1第3次执行!
            线程1第4次执行!
            线程1第5次执行!
            线程1第6次执行!
            线程1第7次执行!
            线程1第8次执行!
            线程1第9次执行!
            主线程第1次执行
            主线程第2次执行
            主线程第3次执行
            主线程第4次执行
            主线程第5次执行
            主线程第6次执行
            主线程第7次执行
            主线程第8次执行
            主线程第9次执行
            主线程第10次执行
            主线程第11次执行
            主线程第12次执行
            主线程第13次执行
            主线程第14次执行
            主线程第15次执行
            主线程第16次执行
            主线程第17次执行
            主线程第18次执行
            主线程第19次执行
        * */
    }
}

2.5,守护线程

  • 调用线程对象的方法setDaemon(true),则可以将其设置为守护线程。
  • JVM的垃圾回收、内存管理等线程都是守护线程。
  • setDaemon(boolean on):将该线程标记为守护线程或用户线程。
  • 当正在运行的线程都是守护线程时,JVM退出。
  • 该方法必须在启动线程前调用。

2.6,线程的中断和死亡

  • 线程中断就是让目标线程停止执行,但它不会使线程立即终止,而是给线程发送一个通知,告诉线程JVM希望退出执行,至于目标线程何时退出,则完全由它自己决定。
public class Demo22
{
    public static void main(String[] args)
    {
        Thread thread = new Thread()
        {
            @Override
            public void run()
            {
                while (true)
                {
                    //判断当前线程是否是中断状态
                    if (this.isInterrupted())
                    {
                        System.out.println("===true===");
                        break;
                    }
                }
            }
        };
        thread.start();
        try
        {
            Thread.sleep(3000);
        } catch (InterruptedException e)
        {
            e.printStackTrace();
        }

        //调用线程中断方法
        thread.interrupt();

        /*
         * 输出结果
         * ===true===
         * */
    }
}
  • 线程会以如下三种方式结束,结束后就处于死亡状态。

    1. run()或call()方法执行完成,线程正常结束。
    2. 线程抛出一个未捕获的Exception或Error。
    3. 直接调用该线程的stop方法结束该线程–该方法容易导致死锁,建议不使用。
  • 注意:不要对一个死亡的线程调用start方法使它重新启动,死亡就是死亡,该线程不可能再次作为线程执行。

public class Demo23
{
    //退出标志
    public static boolean exit = false;

    public static void main(String[] args)
    {
        new Thread()
        {
            @Override
            public void run()
            {
                System.out.println("线程启动了");
                while (!exit)
                {
                    try
                    {
                        Thread.sleep(1000);
                    } catch (InterruptedException e)
                    {
                        e.printStackTrace();
                    }
                }
                System.out.println("线程结束了");
            }
        }.start();

        try
        {
            Thread.sleep(1000 * 5);
        } catch (InterruptedException e)
        {
            e.printStackTrace();
        }

        //5秒后更改退出标志的值,没有这段代码,线程就一直不能停止
        exit = true;
        
        /*
        * 输出结果
        *   线程启动了
            线程结束了
        * */
    }
}
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。