当前位置: 首页 > article >正文

JavaEE 多线程第三节 (lambda方法实现多线程/Thread属性和方法/前台线程后台线程)

欢迎阅读前序课程JavaEE 多线程第二节 (多线程的简单实现Thread/Runable)-CSDN博客

1. lambda方法实现多线程


public class Test {
    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(()->{
            while (true){
                System.out.println("helloworld");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        });
        t.start();

        while (true){
            System.out.println("Hello Main");
            Thread.sleep(1000);
        }
    }
}

2. Thread属性和方法

1. 属性----->名称

public class Test {
    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(()->{
            while (true){
                System.out.println("helloworld");
                try {
                    Thread.sleep(1000);
                 } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        },"自定义线程");
        t.start();

        while (true){
            System.out.println("Hello Main");
            Thread.sleep(1000);
        }
    }
}

可以从jconsole查看

2.方法

public class Test {
    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(()->{
            while (true){
                System.out.println("helloworld");
                try {
                    Thread.sleep(1000);
                 } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        },"自定义线程");
        t.start();

        System.out.println("线程ID"+ t.getId());
        System.out.println("线程名字"+ t.getName());
        System.out.println("线程状态"+ t.getState());
        System.out.println("线程优先级"+t.getPriority());
    }
}

 isAlive

运行结果:

  • t.start() 之前,t.isAlive() 返回 false,因为线程还没有启动。
  • 调用 t.start() 之后,线程开始执行任务,此时 t.isAlive() 返回 true
  • 主线程通过 Thread.sleep(5000) 休眠 5 秒,确保给线程 t 足够的时间去完成任务(线程 t 每次休眠 1 秒,总共循环 3 次,因此需要约 3 秒完成)。
  • t 线程的任务执行完后,t.isAlive() 再次返回 false,因为线程已经结束。

关键点:

  1. 线程状态
    • isAlive() 方法用于检查线程是否还在运行。当线程启动并未终止时,返回 true;否则返回 false
  2. 线程执行过程
    • 你创建了一个线程 t,其任务是在循环中打印 "helloworld" 三次,每次打印后休眠 1 秒。通过 t.start() 启动线程,JVM 会为这个线程分配时间片执行任务。
  3. 线程的生命周期
    • 线程的状态会经历几个阶段:
      1. 新建状态(New):线程 t 刚创建时,还未调用 start()
      2. 就绪状态(Runnable):调用 start() 之后,线程进入就绪状态,等待 JVM 调度执行。
      3. 运行状态(Running):线程被调度并开始执行 run() 方法中的代码。
      4. 终止状态(Terminated):当 run() 方法执行完毕,线程进入终止状态,此时 isAlive() 返回 false

 3. 前台线程后台线程

1. 前台线程 vs 后台线程

  • 前台线程(用户线程):

    • 默认情况下,Java中的线程都是前台线程。
    • JVM不会终止,直到所有前台线程都结束。如果有任何前台线程还在运行,JVM会继续执行。
    • 举例:在你的代码中,如果你不调用 t.setDaemon(true),线程 t 就是一个前台线程,意味着即使 main 方法结束,JVM也不会退出,因为 t 线程在不停地输出 "helloworld"
  • 后台线程(守护线程):

    • 后台线程通常是为其他线程提供服务的线程,比如垃圾回收线程。
    • JVM会在所有前台线程都结束后终止,不管后台线程是否还在运行
    • 通过 Thread.setDaemon(true) 将一个线程设为后台线程。
    • 如果你设置了 t.setDaemon(true),意味着 t 是一个后台线程,当 main 线程(前台线程)结束后,JVM会终止,后台线程 t 也会随之停止,不再继续运行。

2. 结合代码讲解

public class Test {
    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(()->{
            while (true){
                System.out.println("helloworld");
                try {
                    Thread.sleep(1000);
                 } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        },"自定义线程");
        t.setDaemon(true);
        t.start();
        //t变为守护线程不能组织线程结束

    }
}

运行一次就结束了 

3. 执行流程

  • Thread t 是一个线程对象,线程的任务是通过 lambda 表达式定义的,循环输出 "helloworld" 并每秒钟休眠一次。
  • t.setDaemon(true) 这行代码将 t 线程设为守护线程。这意味着,当所有前台线程结束时,守护线程 t 也会结束,而不管它是否仍然在运行。
  • t.start() 启动线程 t,线程进入运行状态,开始打印 "helloworld"
  • 重点:由于 t 是后台线程,当 main 方法执行结束,JVM 会停止所有后台线程并终止运行。因此,t 的运行时间会非常短暂。

4. 前台和后台线程的区别总结

  • 前台线程(用户线程):
    • 会阻止 JVM 退出。
    • 即使所有后台线程结束,前台线程还在运行,JVM 也不会停止。
  • 后台线程(守护线程):
    • 当所有前台线程结束时,JVM 会终止,即使后台线程还在运行。
    • 守护线程通常用于执行一些后台服务,比如垃圾回收。

5. 关于这段代码的实际行为

如果你将 t.setDaemon(true) 改为 t.setDaemon(false)(或者直接不调用它,默认是前台线程),t 就变为前台线程。此时,即使 main 线程结束,JVM 也会继续运行,因为 t 线程还在运行,它会一直每秒钟输出 "helloworld"

然而,使用了 t.setDaemon(true) 后,t 成为后台线程。当 main 线程结束时,t 线程会立即终止,不再输出 "helloworld"

总结:

  • 守护线程通常用于执行后台任务或辅助功能(如垃圾回收器),它不应该是程序的核心逻辑。
  • 用户线程(前台线程)是程序的核心工作线程,确保程序在完成任务后才退出。

http://www.kler.cn/a/370484.html

相关文章:

  • 八大排序--冒泡排序
  • [NOIP2012 提高组] 借教室
  • 3. 后端验证前端Token
  • MyBatis(六)关联查询
  • 多种vue前端框架介绍
  • Excel中函数SIGN()的用法
  • 面试经典 150 题.P88. 合并两个有序数组(001)
  • UE4_Niagara基础实例—10、位置事件
  • 算法的学习笔记—滑动窗口的最大值(牛客JZ59)
  • Unity SpriteEditor 中的图集处理功能
  • 内核上项目【让ntoskrnl.exe保护程序】
  • Vue脚手架
  • 学校NTP电子钟结合教学系统,辅助教学管理
  • Jvm中的堆和栈
  • 微信小程序实现录音,播放录音功能
  • 面试域——岗位职责以及工作流程
  • React如何实现Vue的keepAlive功能
  • 深入了解 kotlinx-datetime:配置与使用指南
  • C++编写台达ME300变频器串口通讯实例
  • 语音提示器-WT3000A离在线TTS方案-打破语种限制/AI对话多功能支持
  • QT-使用QSS美化UI界面
  • Jenkins+RobotFramework 失败用例重执行方案
  • 高级java每日一道面试题-2024年10月22日-JVM篇-JVM堆栈概念,何时销毁对象?
  • 一二三应用开发平台自定义查询设计与实现系列2——查询方案功能实现
  • docker install redis【docker 安装 redis】
  • 【密码学】CKKS全同态加密方案浅析