多线程初阶——线程状态

news2025/1/19 14:28:19

多线程初阶——线程状态

文章目录

  • 多线程初阶——线程状态
    • 1.Thread类及常见构造方法
    • 2.Thread常见的方法
    • 3.线程相关的重要操作
      • 3.1启动线程—start()
      • 3.2中断线程
      • 3.3 等待线程— join()
      • 3.4 获取线程引用
      • 3.5休眠线程—sleep()
    • 4.线程的状态

1.Thread类及常见构造方法

方法说明
Thread()默认无参构造方法
Thread(Runnable target)使用Runnable对象创建线程对象
Thread(String name)创建线程对象,并给线程起名字
Thread(Runnable target,String name)使用Runnable对象创建线程对象,并给线程起名字

给线程起名字

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

            }
        },"线程一");
        t.start();
        while (true){
            System.out.println("main");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

image-20230129200540985

2.Thread常见的方法

属性方法
IDgetId()
名称getName()
状态getState()
优先级getPriority()
是否后台线程isDaemon()
是否存活isAlive()
是否被中断isInterrupted()

说明

getId()

ID是线程唯一标识,不同线程不会重复

getName()

线程的名称

getState()

表示线程当前所处的一个情况

getPriority()

获得线程的优先级

isDaemon()

JVM会在一个进程的所有非后台线程结束后,才会结束运行,这里的后台,和我们常说的手机后台应用类似线程创建的时候,默认是一个前台线程,前台线程可以阻止进程的退出,后台线程不影响进程的退出

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

image-20230129214257735

由于线程是前台进程,需要等待运行结束,进程才结束。代码为死循环,所以将会一直执行。

利用setDaemom()方法将线程设置为后台进程,等主线程执行完,进程就结束了,注意:先设置后台进程,再启动线程

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

    }
}

image-20230129215820274

3.线程相关的重要操作

3.1启动线程—start()

创建Thread对象、重写run方法,只是给线程安排了任务,并没有执行,而调用start方法,才是创建出了线程

3.2中断线程

**线程结束其实就是让线程的入口方法执行完 **

而中断线程,其实就是让线程停止下来,结束入口方法的执行

有2种方法可以中断线程

**方法一:直接用自定义的变量来作为标志位 **

需要给标志位上加volatile关键字

这里我们以李四在银行取钱为例

public class Demo8 {
    private static class MyRunnable implements Runnable {
        public volatile boolean isQuit = false;

        @Override
        public void run() {
            while (!isQuit) {
                System.out.println(Thread.currentThread().getName()
                        + ": 别管我,我忙着转账呢!");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println(Thread.currentThread().getName()
                    + ": 啊!险些误了大事");
        }
    }

    public static void main(String[] args) throws InterruptedException {
        MyRunnable target = new MyRunnable();
        Thread thread = new Thread(target, "李四");
        System.out.println(Thread.currentThread().getName()
                + ": 让李四开始转账。");
        thread.start();
        Thread.sleep(5 * 1000);
        System.out.println(Thread.currentThread().getName()
                + ": 老板来电话了,得赶紧通知李四对方是个骗子!");
        target.isQuit = true;
    }
}

image-20230203010328854

方法二:使用Thread自带的标志位

Thread.interrupted()或者Thread.currenThread().isInterrupted()

public class Demo9 {
 private static class MyRunnable implements Runnable {

     @Override
     public void run() {
         while (!Thread.currentThread().isInterrupted()) {
             System.out.println(Thread.currentThread().getName()
                        + ": 别管我,我忙着转账呢!");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println(Thread.currentThread().getName()
                    + ": 啊!险些误了大事");
        }

    }

    public static void main(String[] args) throws InterruptedException {
        MyRunnable target = new MyRunnable();
        Thread thread = new Thread(target, "李四");
        System.out.println(Thread.currentThread().getName()
                + ": 让李四开始转账。");
        thread.start();
        Thread.sleep(5 * 1000);
        System.out.println(Thread.currentThread().getName()
                + ": 老板来电话了,得赶紧通知李四对方是个骗子!");
        thread.interrupt();
    }
}

运行结果

image-20230203204711356

这时抛出了InterruptedException异常

这是为什么呢?

由于线程的有效任务是打印一句话,这个操作耗时比较小,大部分时间线程都在sleep状态,正常来说,当线程在运行真正有效任务时去中断才是一个有效的中断,而在线程休眠的时候中断,其实是把休眠给中断了,而休眠本身没有到指定的时间,所以抛出了InterruptedException异常

当我们去掉线程中的休眠时,结果如下

image-20230203220249387

这时候线程才真正的中断了

3.3 等待线程— join()

我们知道线程之间的执行顺序是根据系统调度随机执行的,但有时我们需要等待一个线程执行完,再执行下一个线程,这时我们需要一个方法明确等待线程结束

public class Demo10 {
    public static void main(String[] args) throws InterruptedException {
        Runnable target = () -> {
            for (int i = 0; i < 3; i++) {
                System.out.println(Thread.currentThread().getName() + ":正在工作!");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println(Thread.currentThread().getName() + "结束了工作");
        };
        Thread thread1 = new Thread(target, "李四");
        Thread thread2 = new Thread(target, "王五");
        System.out.println("李四先工作");
        thread1.start();
        thread1.join();
        System.out.println("李四结束了工作,王五开始工作");
        thread2.start();
        thread2.join();
        System.out.println("王五结束了工作");
    }
}

image-20230203221145829

join()其他方法

public void join()等待线程结束(一直等,知道线程执行的任务结束)
public void join(long millis)等待线程结束,但等待millis毫秒
public void join(long millis, int nanos)同理

3.4 获取线程引用

private static Thread currentThread()

返回当前线程对象的引用

3.5休眠线程—sleep()

让线程休眠休眠一会

图解sleep()的具体使用

image-20230204002702109

4.线程的状态

在Java线程分为6种状态

1. NEW:创建好了一个Java的Thread对象,并安排好了任务,没有调用start()方法之前,和PCB没有关系

2. RUNNABLE:运行+就绪状态,在执行任务时的一个常态之一

3. TIMED_WAITING:指定了一个时间的阻塞队列,过时不候

4. WAITING :没有指定时间的等待,一直死等

5. BLOCK:等待锁的状态

6. TERMINATED :结束,完成状态,PCB已经被销毁了,但是Java对象还在

查看线程状态

public class Demo14 {
    public static void main(String[] args) throws InterruptedException {
        Thread thread=new Thread(()->{
            for (int i = 0; i < 5; i++) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        System.out.println("线程创建之前:"+thread.getState());
        thread.start();
        Thread.sleep(1000);
        System.out.println("启动线程,创建好PCB后:"+thread.getState());
        thread.join();
        System.out.println("线程执行完成后:"+thread.getState());
    }
}

image-20230204004138603

线程之间相互转换

image-20230204004728035
觉得不错就留下你的三连吧

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/197573.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

前端js实现根据文件url批量压缩下载成zip包

前言 项目开发中&#xff0c;产品经理提了这样一个需求&#xff1a;将系统中的附件实现批量打包下载功能。本来系统中是有单个下载及批量下载功能&#xff0c;现在应业务方的需求&#xff0c;需要多加个批量打包下载。 初步设想是&#xff1a;由后端编写接口实现。但后来经过思…

从事测试开发8年,聊聊我是怎么从0基础到年薪40万的

本人从事测试开发8年多&#xff0c;之前在猪场工作&#xff0c;年薪突破40W&#xff0c;算是一个生活过得去的码农。&#xff08;仅代表本人&#xff09;目前从事软件测试行业的薪资待遇还是很不错的&#xff0c;所以如果朋友们真的对软件测试感兴趣的话可以坚持学下去&#xf…

Java native agent学习笔记-从加载到log4j漏洞检测

记录一下java native agent的学习过程,也顺便造一个检测log4j漏洞的轮子: java native agent相比java agent最大的好处是快,C写的,快的一笔,但是最大的坏处是非常麻烦,毕竟你拿个面过程的语言怼面对象的肯定是比较麻烦的。 本次学习的目的是做个加载器,动态加载agent,然后再实…

研究人员发布 VMware vRealize Log RCE 漏洞,立即打补丁

Horizon3 攻击团队的安全研究人员将于下周发布一个针对漏洞链的漏洞利用程序&#xff0c;以在未打补丁的 VMware vRealize Log Insight 设备上获得远程代码执行。 vRealize Log Insight 现在称为 VMware Aria Operations for Logs&#xff0c;它使 VMware 管理员可以更轻松地分…

每日学术速递2.4

CV - 计算机视觉 | ML - 机器学习 | RL - 强化学习 | NLP 自然语言处理 Subjects: cs.LG、cs.AI 1.Neuro Symbolic Continual Learning: Knowledge, Reasoning Shortcuts and Concept Rehearsal 标题&#xff1a;神经象征性的持续学习&#xff1a;知识、推理捷径和概念排练…

必须掌握的网络安全知识

没有网络安全&#xff0c;就没有国家安全。网络安全和保密防护&#xff0c;是机关单位日常工作中不可忽视的重要问题。尤其在涉密单位工作的人员&#xff0c;因工作性质特殊&#xff0c;不仅要了解非涉密网络的安全操作常识&#xff0c;更要重点了解涉密网络的规范行为要点&…

2021年上半年信息系统项目管理师真题与答案完整版(综合知识、案例分析、论文)

1、 国家信息化体系包括六个要素&#xff0c;其中&#xff08;&#xff09;是信息化体系六要素中的龙头&#xff0c;是国家信息化建设的主阵地&#xff0c;集中体现了国家信息化建设的需求和效益。A、信息资源 B、信息技术应用 C、信息网络 D、信息化政策法规和标准规范0参考答…

若依代码生成器------数据库篇

继上一篇《若依代码自动生成器研究-表查询篇》&#xff0c;我们继续来学习若依系统中的代码生成逻辑。 导入表之Sql查询 在菜单栏点击“代码生成”&#xff0c;在右侧栏中点击“导入”按钮&#xff0c;在文章若依中的代码自动生成器研究-表查询篇中&#xff0c;我们已经一直…

三十六、Kubernetes1.25中数据存储第一篇

1、概述在前面已经提到&#xff0c;容器的生命周期可能很短&#xff0c;会被频繁地创建和销毁。那么容器在销毁时&#xff0c;保存在容器中的数据也会被清除。这种结果对用户来说&#xff0c;在某些情况下是不乐意看到的。为了持久化保存容器的数据&#xff0c;kubernetes引入了…

【深度学习】对SSD与Retina的理解

SSD 正负样本选择 同YOLO 选择与GT IOU最大的anchor作为正样本。(此时正负样本很不平衡)对于剩余未匹配anchor,将与GT IOU超过0.5的作为正样本。这样一个GT就可以匹配多个anchor,增加正样本的数量。(此时负样本依然多于正样本)hard negative mining,难负样本挖掘。将所有…

重定向的概述和使用(基于web方面),很简单

大家好&#xff0c;今天分享一下重定向的概述以及使用 我们要知道&#xff0c;重定向(Redirect)就是通过各种方法将各种网络请求重新定个方向转到其它位置 同时&#xff0c;重定向有好几类 1.网页重定向、 2.域名的重定向、 3.路由选择 4. Linux上的文件重定向操作 就是要知…

QTransform的使用

目录引言基础知识缩放矩阵平移矩阵旋转矩阵矩阵乘法实际使用实现思路完整代码参考资料引言 A transformation specifies how to translate, scale, shear, rotate or project the coordinate system, and is typically used when rendering graphics. A QTransform object can …

6 -【Faster R-CNN 代码精读】之 Proposals 、 Filter Proposals

6 -【Faster R-CNN 代码精读】之 Proposals 、 Filter Proposals1、前言2、数据回顾3、计算候选框位置&#xff08;proposal coordinates&#xff09;4、筛选候选框&#xff08;filter proposals&#xff09;及相关处理1&#xff09;筛选出 预测概率 排前 2000 的proposals2&am…

TCP协议面试灵魂12 问(四)

005: 介绍一下 TCP 报文头部的字段 报文头部结构如下(单位为字节): 请大家牢记这张图&#xff01; 源端口、目标端口 如何标识唯一标识一个连接&#xff1f;答案是 TCP 连接的四元组——源 IP、源端口、目标 IP 和目标端口。 那 TCP 报文怎么没有源 IP 和目标 IP 呢&#x…

2021年下半年信息系统项目管理师《综合知识》《案例分析》《论文》真题与答案

1、“十四五”期间&#xff0c;我国关注推动政务信息化共建共用、推动构建网络空间命运共同体&#xff0c;属于()的建设内容.A、科技中国 B、数字中国 C、制造强国 D、创新强国0参考答案&#xff1a;B2、()关注的是业务&#xff0c;以业务驱动技术&#xff0c;强调IT与业务的对…

零基础学FPGA(八):可编程逻辑单元(基本结构,Xilinx+Altera)

目录日常唠嗑一、概述二、基于多路选择器的逻辑单元1、基于多路选择器的逻辑单元&#xff08;早期&#xff09;2、基于PLD结构的逻辑单元&#xff08;类CPLD&#xff09;3、基于查询表的逻辑单元&#xff08;目前主流&#xff09;三、Xilinx基本结构四、Altera 基本结构日常唠嗑…

Java语言还能火多久? 还能选择Java开发吗?

​​整个互联网行业“不进则退&#xff0c;慢进亦退”。对于用人要求持续增高的互联网企业来说&#xff0c;中高级Java程序员才是当下市场最紧缺的。 现在的你&#xff0c;是十年前你的决定&#xff0c;十年后的你&#xff0c;是现在你的决定。选择很重要 为什么选择Java开发…

代码随想录算法训练营第六十天_第九章_动态规划 | 647. 回文子串、516.最长回文子序列、动态规划总结篇

LeetCode 647. 回文子串 给你一个字符串 s &#xff0c;请你统计并返回这个字符串中 回文子串 的数目。具有不同开始位置或结束位置的子串&#xff0c;即使是由相同的字符组成&#xff0c;也会被视作不同的子串。 视频讲解https://www.bilibili.com/video/BV17G4y1y7z9/?spm_i…

Linux 进程知识总结

✅作者简介&#xff1a;热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏&#xff1a;Linux操作…

高阶数据结构之哈希的应用

文章目录位图&#xff08;bitMap&#xff09;位图的实现将数据添加到位图中检查数据是否在位图中存在将数据的对应位置置为0位图的应用布隆过滤器为什么会有误差布隆过滤器的实现布隆过滤器的删除使用Google下的guava组件操作布隆过滤器布隆过滤器的缺陷布隆过滤器的使用场景海…