【Java】Thread详解

🍒前言

本文将从以下几方面来展开对Thread的介绍。
1.线程创建 2.线程中断 3.线程等待 4.线程休眠
在前面的文章中,已经总结了关于Thread的一些理解。
在阅读本文之前,最好对其有一些基础的了解。
文章链接: 【JavaSE】进程是什么?
文章链接: 【JavaSE】初识线程,线程与进程的区别
文章链接: 【JavaSE】Thread类中run和start的区别

文章目录

  • 🍒前言
  • 🍇线程的创建
    • 🍐1.继承 Thread 类
    • 🍐2.实现Runnable接口
    • 🍐3.匿名内部类
    • 🍐4.匿名内部类创建 Runnable ⼦类对象
    • 🍐5.lambda 表达式创建 Runnable ⼦类对象
  • 🍎线程中断
    • 🥝1.自己设定条件
      • **缺点**
    • 🥝2.使用interrupt和isInterrupted方法
  • 🍆线程等待
  • ✍线程休眠

🍇线程的创建

🍐1.继承 Thread 类

class MyThread extends Thread{@Overridepublic void run() {while (true){System.out.println("hello thread");try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}}
}
public class demo1 {public static void main(String[] args) throws InterruptedException {Thread t = new MyThread();t.start();while (true){System.out.println("hello main");Thread.sleep(1000);}}
}

🍐2.实现Runnable接口

class MyRunnable implements Runnable{@Overridepublic void run() {while (true){System.out.println("hello thread2");try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}}
}public class demo2 {public static void main(String[] args) throws InterruptedException {Thread t = new Thread(new MyRunnable());t.start();while (true){System.out.println("hello main2");Thread.sleep(1000);}}
}

🍐3.匿名内部类

public class demo3 {public static void main(String[] args) throws InterruptedException {Thread t = new Thread(){@Overridepublic void run() {while (true){System.out.println("hello thread3");try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}}};t.start();while (true){System.out.println(" hello main");Thread.sleep(1000);}}
}

🍐4.匿名内部类创建 Runnable ⼦类对象

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

🍐5.lambda 表达式创建 Runnable ⼦类对象

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

🍎线程中断

终止线程,在Java中所有的终止程序都只是“提醒,建议”。真正的是否结束都是由线程本体 自己决定的。

在系统原生的线程中,是有办法让别的线程强制终止的,但这种设定不太好,所以Java没有采纳
主要原因还是线程之间的调度是随机的。

🥝1.自己设定条件

之所以可以结束,是因为thread线程外面写了isRunning这样的条件,所以才能控制
如果thread代码不这样写,那么thread都会继续执行,不会在意外面的条件

最终决定权还是在thread手中。

  private static boolean isRunning = true;public static void main(String[] args) {Thread thread  = new Thread(()->{while (isRunning){//自己书写条件控制线程的结束System.out.println("hello thread");try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}});thread.start();try {Thread.sleep(3000);//三秒之后  } catch (InterruptedException e) {throw new RuntimeException(e);}isRunning = false;//三秒之后设置 条件 终止线程System.out.println("end Thread");}

运行结果如下

在这里插入图片描述

缺点

在这里插入图片描述

🥝2.使用interrupt和isInterrupted方法

    public static void main(String[] args) throws InterruptedException {Thread t  = new Thread(()->{// t.isInterrupted();while (!Thread.currentThread().isInterrupted()){System.out.println("hello thead");try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}});t.start();Thread.sleep(3000);t.interrupt();}

在这里插入图片描述

在这里插入图片描述

运行程序
发现3s之后,线程确实是结束了。但是是以抛出异常中断的情况结束,

在这里插入图片描述

这样会使结果不那么美观。那么接下来就要解决这样的问题。
解决方法
我们不抛出异常,而是打印出异常。
继续运行,看看结果是怎样的。

在这里插入图片描述

在这里插入图片描述

我们可以看到结果中,打印出了异常,而线程并没有结束

我们确确实实使用了interrupt方法,使标志位修改成了true了,那为什么线程还会继续执行呢?

在这里插入图片描述
在这里插入图片描述

🍆线程等待

因为线程是随机调度的,为了解决这样的问题,从而引入了线程等待。

使用join()

 public static void main(String[] args) throws InterruptedException {Thread t1 = new Thread(()->{for (int i = 0; i < 3; i++) {System.out.println("hello t1");try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}});Thread t2 = new Thread(()->{for (int i = 0; i < 3; i++) {System.out.println("hello t2");try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}});t1.start();t2.start();t1.join();//加入条件t2.join();//System.out.println("end main");}

运行结果如下
main线程调用t1.join() t2.join(),t1 t2 继续执行 main线程等待
t1和t2谁先结束,这是未知的
而t1 和 t2 比main先结束,这是已知的。

如果想要定义t1和t2的先后结束顺序
就在对应的t1或t2线程内调用join()方法

在这里插入图片描述
join还有一个带参数的方法
不带参数的join方法就是所谓的“死等”
在这里插入图片描述

✍线程休眠

线程休眠sleep控制的是“线程休眠的时间”,而是不是“两个代码执行的间隔时间”
举例

  public static void main(String[] args) throws InterruptedException {System.out.println(System.currentTimeMillis());Thread.sleep(1000);System.out.println(System.currentTimeMillis());}

由打印结果可以看出,这里并不是精准的1000,

在这里插入图片描述

此处sleep是指线程阻塞的时间,在这个时间段内是无法抢占CPU的执行权的

而时间结束,线程由阻塞状态变为就绪状态
但这并不意味着它立即就能到CPU上去执行。

以上就是本文所有内容,如果对你有帮助的话,点赞收藏支持一下吧!💞💞💞

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于lora技术微调Gemma(2B)代码实践

一、前置条件 获得模型访问权&#xff0c;选择Colab运行时&#xff0c;配置训练环境。 先在Kaggle上注册&#xff0c;然后获得Gemma 2B 的访问权&#xff1b; 然后在Google colab 配置环境&#xff0c;主要是GPU的选择&#xff0c;免费的是T4&#xff0c;建议采用付费的A100…

C++——list类及其模拟实现

前言&#xff1a;这篇文章我们继续进行C容器类的分享——list&#xff0c;也就是数据结构中的链表&#xff0c;而且是带头双向循环链表。 一.基本框架 namespace Mylist {template<class T>//定义节点struct ListNode{ListNode<T>* _next;ListNode<T>* _pre…

【重学C语言】三、C语言最简单的程序

【重学C语言】三、C语言最简单的程序 最简单的程序头文件使用尖括号 < >使用双引号 ""区别与注意事项示例 主函数认识三个错误 常量和变量常量ASCII 码表转义字符 关键字数据类型关键字存储类关键字修饰符关键字控制流程关键字函数相关关键字其他关键字 变量变…

Linux 恶意软件“Migo”针对 Redis 进行加密劫持攻击

安全研究人员遇到了一种新的加密劫持活动&#xff0c;该活动使用一种名为 Migo 的新恶意软件&#xff0c;该恶意软件针对 Linux 主机上的 Redis 服务器。在 Cado Security 研究人员注意到在野外利用 Redis 系统的新命令后&#xff0c;该活动曝光了。 初始访问 根据 Cado secu…

RUST语言基本数据类型认识

1.RUST的基本数据类型参考: 2.使用RUST数据类型声明变量并赋值: let a:i8=1;//8位有符号整数let a1:u8=2;//8位无符号整数let b:i16=1;//16位有符号整数let b1:u16=2;//16位无符号整数let c:i32=1;//32位有符号整数let c1:u32=2;//32位无符号整数let d:i64=1;//64位有符号整数l…

公众号爆文策略与实践:揭秘千万阅读量的秘密

1. 引言 介绍公众号爆文的重要性&#xff0c;以及分享个人通过每天投入半小时赚到30倍门票的经验。强调跟上大佬步伐&#xff0c;提升认知的重要性。 2. 爆文的底层逻辑 2.1 推荐的底层逻辑 内容分发机制的变化&#xff0c;从仅限于直接关注到通过搜索、浏览推荐等多种方式…

【项目实战经验】DataKit迁移MySQL到openGauss(上)

前言 本文将分享DataKit迁移MySQL到openGauss的项目实战&#xff0c;供广大openGauss爱好者参考。 1. 下载操作系统 https://www.openeuler.org/zh/download https://support.huawei.com/enterprise/zh/doc/EDOC1100332931/1a643956 https://support.huawei.com/enterprise…

封装一个vue3的公共组件

在Vue 3中&#xff0c;封装公共组件的场景包括但不限于以下几种情况&#xff1a; 重复使用的组件&#xff1a;如果你发现某个组件在多个地方重复使用&#xff0c;那么将其封装成公共组件是很有意义的。比如&#xff0c;页面中的各种表单控件&#xff08;输入框、下拉框、日期选…

硬件开发文档规范

本文出发点&#xff1a; 一般来说&#xff0c;越是大公司越注重开发文档的规范性&#xff0c;因为这样最大的好处是能够保证开发的连贯性&#xff0c;也就是即使有员工离职了&#xff0c;只要开发文档是齐全的&#xff0c;新员工入职后&#xff0c;就能够很快接手工作&#xf…

Linux驱动学习:从Linux主机nfs共享文件到uboot

第一步&#xff1a;在Linux主机上开启NFS服务&#xff0c;使用如下命令安装NFS服务&#xff1a; sudo apt-get install nfs-kernel-server rpcbind 第二步&#xff1a;创建一个文件夹用于共享&#xff0c;直接以nfs命名就行&#xff1a; 第三步&#xff1a;打开nfs服务配置文…

arm裸机(1)、点灯|按键

芯片是S3C2440 首先看原理图&#xff0c;led_1234分别对应引脚GPB 5678 设置引脚为输出 向寄存器相应位写入 #define GPBCON (*(volatile unsigned long *)0x56000010) //p5 6 7 8 void led_init(void) {GPBCON & ~(0x3 << 10);GPBCON | (0x1 <<…

LeetCode-19. 删除链表的倒数第 N 个结点【链表 双指针】

LeetCode-19. 删除链表的倒数第 N 个结点【链表 双指针】 题目描述&#xff1a;解题思路一&#xff1a;双指针解题思路二&#xff1a;优化解题思路三&#xff1a;0 题目描述&#xff1a; 给你一个链表&#xff0c;删除链表的倒数第 n 个结点&#xff0c;并且返回链表的头结点。…