Thread 类基本用法详解

news2024/11/24 20:54:00

Thread 类基本用法详解

  • Thread类的作用
  • 线程创建
    • 继承 Thread, 重写 run
    • 实现 Runnable, 重写 run
    • 继承 Thread, 重写 run, 使用匿名内部类
    • 实现 Runnable, 重写 run, 使用匿名内部类
    • 使用 lambda 表达式(==最推荐==)
  • 线程中断
    • 1.使用标志位来控制线程是否要停止
    • 2.使用Thread自带的标志位来控制线程是否要停止
  • 线程等待

Thread类的作用

Thread是Java操作多线程最核心的类。

线程创建

Java中创建线程的方法有很多种!!!

继承 Thread, 重写 run

//继承Thread类并重写run方法创建一个线程
class Thread01 extends Thread{
    @Override
    public void run() {
        System.out.println("hello,thread");
    }
}
public class ThreadDemo {
    public static void main(String[] args) {
        //实例化一个线程对象
        Thread01 t=new Thread01();
        //真正去申请系统线程,参与CPU调度
        t.start();
    }
}

实现 Runnable, 重写 run

//通过继承Runnable接口并实现run方法
class MyRunnable implements Runnable{
    @Override
    public void run() {
        System.out.println("hello,thread");
    }
}
public class ThreadDemo {
    public static void main(String[] args) {
         //实例化Runnable对象
        MyRunnable runnable=new MyRunnable();
        //实例化线程对象并绑定任务
        Thread t=new Thread(runnable);
        t.start();
    }
}

继承 Thread, 重写 run, 使用匿名内部类

 //通过Thread匿名内部类的方法创建一个线程
public static void main(String[] args) {
       Thread t=new Thread(){
            //指定线程任务
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName());
            }
        };
        t.start();
}

实现 Runnable, 重写 run, 使用匿名内部类

//通过Runnable匿名内部类创建一个线程
   public static void main(String[] args) {
      Thread t=new Thread(new Runnable() {
          //指定线程的任务
          @Override
          public void run() {
              System.out.println(Thread.currentThread().getName());
          }
      });
      t.start();
   }

使用 lambda 表达式(最推荐)

//通过Lambda表达式的方式创建一个线程
public static void main(String[] args) {
    Thread t=new Thread(()->{
        System.out.println("Hi");
    });
    t.start();
}

上述方法,只是语法规则不同,本质上是一样的方式,创造出的线程并无不同。

面试题一:请说明Thread类中run和start的区别
答案:
作用功能不同:
a.run方法的作用是描述线程具体要执行的任务;
b.start方法的作用是真正在操作系统内核里创建线程,并让新线程调用run方法。
运行结果不同:
a.run方法是一个类中的普通方法,主动调用和调用普通方法一样,会顺序执行一次。
b.start调用方法后,start方法内部会调用Java本地方法(封装了对系统底层的调用)真正的启动线程,并执行run方法中的代码,run方法执行完成后,线程进入销毁阶段。

线程中断

中断的意思不是指让线程立即就停止,而是通知线程应该要停止,是否真的停止,取决于线程这里具体的代码写法。

1.使用标志位来控制线程是否要停止

    public static boolean flag=true;
    public static void main(String[] args) throws InterruptedException {

        Thread t=new Thread(()->{
            while (flag){
                System.out.println("hello Thread");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        t.start();
        Thread.sleep(3000);
        //在主线程里就可以随时通过flag变量的取值,来操作t线程是否结束
        flag=false;

    }
  • 自定义变量这种方式不能及时响应,尤其是在sleep休眠的时间比较久的时候。
  • 这个代码之所以能够起到修改flag, t线程就结束,完全取决于 t 线程内部的代码。
  • 代码里通过flag控制循环。因此这里只是告诉让这个线程结束,这个线程是否要结束,啥时候结束,都取决于 t 线程内部代码。

2.使用Thread自带的标志位来控制线程是否要停止

public static void main(String[] args) throws InterruptedException {

    Thread t=new Thread(()->{
        while (!Thread.currentThread().isInterrupted()){
            System.out.println("hello Thread");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    });
    t.start();
    Thread.sleep(3000);
    t.interrupt();
}

Thread.currentThread():这是Thread类的静态方法,通过这个方法可以获取到当前线程,哪个线程调用这个方法,就得到哪个线程的对象引用,类似于this。
isInterrupted():判断线程是否终止,为true表示被终止,为false表示未被终止。
t.interrupt() :在上述代码中,主线程调用t.interrupt(),相当于主线程通知 t 线程要终止。

在这里插入图片描述

此处interrupt会做两件事:
1.把线程内部的标志位(boolean)给设置成true。
2.如果线程在进行sleep,就会触发异常,把sleep唤醒。
注意:
在唤醒sleep的时候,会把刚才设置的这个标志位,再设置回false。(清空了标志位)
这就导致上述代码在sleep的异常被catch完了之后,循环还要继续执行!!
上述代码执行结果:
在这里插入图片描述
问题一:为啥sleep要清除标志位?
唤醒sleep之后,线程到底是否要终止,到底是立即终止还是稍后终止,取决于线程内部代码。

线程等待

线程等待是指一个线程在执行过程中暂停自己的运行,并等待其他线程完成一定的操作后再继续执行。简单来说,就是控制多个线程的执行顺序。
线程等待的实现方式有很多种,其中最常见的方式是使用线程的join()方法。当一个线程调用另一个线程的join()方法时,它会被阻塞,直到被调用的线程执行完毕并退出。

在这里插入图片描述

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

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

相关文章

软件测试商城项目----优惠券测试流程

优惠券冒烟测试 后台添加优惠券,前端领取,消费并成功扣除对应金额,如果冒烟测试不通过不进行下面的测试。 优惠券基本信息测试 (1)优惠券名称 (2)优惠券副标题 (3)优惠券…

ubuntu2204server虚拟机创建

ubuntu2204 虚拟机创建系统安装系统配置 虚拟机创建ubuntu2204,然后配置清华源,修改网卡已经ssh文件,实现远程连接 虚拟机创建 一路回车默认到创建磁盘 一路回车到自定义硬件 添加一块网盘,其他的是否添加自己根据实际情况&…

【C刷题笔记】找单身狗问题

目录 版本1:在数组内只有一个元素没有成对出现 版本2:在数组内有两个元素没有成对出现 第一步:异或所有元素,异或就是相同为0,相异为1 第二步:计算ret的二进制中哪一位元素是1 第三步:开始分组异或 1.分组: 2.异或 版本1:在数组内只有一个元素没有成对出现 单…

基于C/C++将派生类赋值给基类的详细讲解

目录 将派生类对象赋值给基类对象 将派生类指针赋值给基类指针 将派生类引用赋值给基类引用 本期推荐书目 在 C/C中经常会发生数据类型的转换,例如将 int 类型的数据赋值给 float 类型的变量时,编译器会先把 int 类型的数据转换为 float 类型再赋值&a…

华为OD机试 Java 实现【查找兄弟单词】【牛客练习题 HJ27】,附详细解题思路

一、题目描述 定义一个单词的“兄弟单词”为:交换该单词字母顺序(注:可以交换任意次),而不添加、删除、修改原有的字母就能生成的单词。 兄弟单词要求和原来的单词不同。例如: ab 和 ba 是兄弟单词。 ab …

三防工业平板电脑搭载大容量聚合物锂电池,满足全天候移动式作业

在制造业、物流业等行业中,电脑经常会接触到水,因此防水是非常重要的。工业三防平板电脑采用了特殊的防水技术,能够在水中工作,即使在雨天或水花溅到电脑上时也不会受到损坏。 三防工业平板电脑采用8核ARM架构处理器,2…

QML开发避坑指南(四):ImageProvider的使用

(1)引子 首先,ImageProvider是为QML应用提供的、一种先进的图像加载方式。 作者建议从三点理解其定义: 加载方式的差异: 相比本地资源的加载方式:source : “qrc:///前缀/demo.jpg”。 ImageProvider方式…

使用 ChatGPT API 构建系统(三):思维链推理

今天我学习了DeepLearning.AI的 Building Systems with the ChatGPT API 的在线课程,我想和大家一起分享一下该门课程的一些主要内容。 下面是我们通过Open API来访问ChatGPT模型的主要代码: import openai#您的openai的api key openai.api_key YOUR-O…

使用FS_Hi3861鸿蒙开发板编译时常见的一些问题

本文档支持的是下面的产品 华清远见 FS-Hi3861https://gitee.com/HiSpark/hi3861_hdu_iot_application/blob/master/src/vendor/hqyj/fs_hi3861/doc/%E5%8D%8E%E6%B8%85%E8%BF%9C%E8%A7%81%20FS_Hi3861%E5%BC%80%E5%8F%91%E6%8C%87%E5%AF%BC.md 目录 在添加第三方库完成后&a…

想要精通算法和SQL的成长之路 - 下一个排列

想要精通算法和SQL的成长之路 - 下一个排列 前言一. 下一个排列二. 下一个更大元素III 前言 想要精通算法和SQL的成长之路 - 系列导航 一. 下一个排列 原题链接 整数数组的一个 排列 就是将其所有成员以序列或线性顺序排列。 例如,arr [1,2,3] ,以下…

Wi-Fi 6还没用熟,Wi-Fi 7就要来了,性能“高攀不起”!

Wi-Fi作为一种无线通信技术,在现代生活中扮演着重要的角色。随着无线设备数量的不断增加和对高速、高容量网络的需求日益增长,Wi-Fi技术不断发展演进。在过去的几十年中,我们见证了多个Wi-Fi技术标准的推出,其中最新的一代是Wi-Fi…

Spring Boot集成Redisson布隆过滤器案例

1 什么是布隆过滤器 布隆过滤器实际上是一个非常长的二进制向量(bitmap)和一系列随机哈希函数。那什么又叫哈希函数呢?哈希函数指将哈希表中元素的关键键值通过一定的函数关系映射为元素存储位置的函数。(HashMap源码) 布隆过滤器的优点&…

python基于轻量级CNN模型开发构建手写藏文数字识别系统

最近做的很多工作都是跟手写性质的数据集有关的,比如:手写汉字、手写甲骨文、手写数字、手写字母等等,今天主要做的实践是对藏文中的手写数字进行识别分析,在我之前的博文中有很多相关的实践分析,感兴趣的话可以自行移…

图解Redis中的9种数据结构

如图所示,Redis中提供了9种不同的数据操作类型,他们分别代表了不同的数据存储结构。 图2-17 数据类型 String类型 String类型是Redis用的较多的一个基本类型,也是最简单的一种类型,它和我们在Java中使用的字符类型什么太大区别&…

MyBatis 万字进阶

文章目录 一. 增, 删, 改 操作1.1 修改操作1.2 删除操作1.3 添加操作1.3.1 返回受影响行数1.3.2 返回 id 二. 查询操作2.1 单表查询2.1.1 参数占位符 ${} 和 #{}2.1.2 SQL 注入问题2.1.3 ${} 的优点2.1.4 Like 查询 2.2 多表查询2.2.1 返回类型 resultType2.2.2 返回字典映射 r…

Linux内核进程创建流程

本文代码基于Linux5.10 内容主要参考《Linux内核深度解析》余华兵 当Linux内核要创建一个新进程时, 流程大致如下 ret fork(); if (ret 0) {/* 子进程装载程序 */ret execve(filename, argv, envp); } else if (ret > 0) {/* 父进程 */ } 大致可以分为创建新…

pagehelper分页插件(SpringBoot,Mybatis整合前后端分析)

前言:在学习项目的过程中遇到了数据分页的功能,单纯的js前端不能处理大的数据量,需要后端整理好数据发送给前端,那么使用分页插件无疑是个好选择. 目录 pagehelper依赖 接口方法mapper Mybatis Service ServiceImpl PageResu…

[IJCAI 2022] 基于个性化掩码的实用安全联合推荐

Practical and Secure Federated Recommendation with Personalized Mask | SpringerLink 摘要 联合推荐解决了推荐系统的数据筒仓和隐私问题。目前的联合推荐系统主要利用密码学或混淆方法来保护原始评分不被泄露。然而,前者带来了额外的通信和计算成本&#xff0…

day 49 :121. 买卖股票的最佳时机;122. 买卖股票的最佳时机 II;123. 买卖股票的最佳时机 III

买卖股票 121. 买卖股票的最佳时机:一次买入卖出1. 贪心算法2. 动态规划1. dp数组以及下标名义2. 递归公式3. dp数组如何初始化4. 代码 122. 买卖股票的最佳时机 II:可以多次买入卖出2. 动态规划1. dp数组以及下标名义2. 递归公式3. dp数组如何初始化4. 代码 123. 买…

Linux_进程

目录 一.进程概念与子进程 1.进程基本概念 2.通过系统调用创建子进程-fork 二.进程状态 1、一般进程状态 2、Linux操作系统的进程状态 三.环境变量 1.概念 2.环境变量组织与获取 3.配置文件 4.环境变量的全局属性​编辑 5.命令行参数 四.进程优先级 1.查看系统进…