JAVA----Thread

Thread

这里写目录标题

  • Thread
    • 线程
      • Thread 第 1 种写法
        • 此外, t.start()的作用
      • Thread 第 2 种写法
      • Thread 第 3 种写法
      • Thread 第 4 种写法
      • Thread 第 5 种写法

线程

本身是操作系统提供的, 操作系统提供了 API 以让我们操作线程, JVM 就对操作系统 API 进行了封装.
线程这里, 则提供了 Thread 类, 表示线程. 利用类中的创建的实例, 以及实例里面创建的一系类方法, 我们就可以完成多线程编程了.

Thread 第 1 种写法

代码示例

package thread;
class MyThread extends Thread{//注解: 相当于是 提示编译器, 进行更严格的检查@Overridepublic void run() {//run(): 描述线程的工作System.out.println("hello thread");}
}public class Demo1 {public static void main(String[] args) {Thread t = new MyThread();t.start();}
}

结果

hello threadProcess finished with exit code 0//进程结束

上述代码中, 有 2 个线程:

  1. t 线程;
  2. main 方法所在的线程 (主线程).

但以上执行, 无法很直观的看见两个线程的执行, 我们再对其进行修改.
代码如下

package thread;
class MyThread extends Thread{//注解: 相当于是 提示编译器, 进行更严格的检查@Overridepublic void run() {//run(): 描述线程的工作while(true){System.out.println("hello thread");}}
}public class Demo1 {public static void main(String[] args) {Thread t = new MyThread();t.start();while(true){System.out.println("hello main");}}
}

运行结果是两者交替 并发 执行.

我们可以使用 jdk 中包含的 jconsole 工具来观察线程.

在这里插入图片描述
thread.Demo1则是我们创建的线程, 选中连接.

在这里插入图片描述
再点击 线程

在这里插入图片描述
我们可以看到, 执行一个文件, 有 15 个线程, 并且在下方能看见 main 和 Thread-0 两个线程.

我们分别点击main 与 Thread线程
在这里插入图片描述
在这里插入图片描述
如图, 我们可以看到线程的调用栈, main 在调用sleep() 方法, Thread 有一个run() 方法在调用sleep().

我们同样可以打开任务管理器

在这里插入图片描述

我们可以看见这一个 循环, 吃了很多的CPU资源

故而我们利用 sleep() 方法, 来让线程主动进入"阻塞状态", 主动离开 CPU, 睡眠 / 休眠 一段时间.

try {Thread.sleep(1000);//休眠1秒(单位 ms)
} catch (InterruptedException e) {throw new RuntimeException(e);
}

等时间到了之后, 线程就会解除 “阻塞状态”, 重新被调度到 CPU 上执行.

package thread;
class MyThread extends Thread{//注解: 相当于是 提示编译器, 进行更严格的检查@Overridepublic void run() {//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");try{Thread.sleep(1000);}catch (InterruptedException e) {e.printStackTrace();}}}
}

在这里插入图片描述
此时的 CPU 占用率大幅降低.

此时涉及到一个问题
在未来实际开发中, 发现服务器程序, 消耗 CPU 资源超出预期, 如何排查这个问题.

则 先需要确认哪个线程消耗的 CPU 比较高: 利用第三方工具找到此线程, 确定以后, 进一步 排查 线程中是否有类似 “非常快速” 的循环.
然后确认 此循环是否应该这么快, 若应该, 则升级 CPU. 若不应该, 则需要在循环中引入 等待操作(不一定是sleep() ).

然而
每个线程打印可能是 main 在前, 也可能是 thread 在前, 多个线程的调度是无序的, 在操作系统内部也称为 “抢占式执行”. 充满了随机性, 正是如此, 使用多线程是难以预测的.

此外, t.start()的作用
package thread;
class MyThread extends Thread{//注解: 相当于是 提示编译器, 进行更严格的检查@Overridepublic void run() {//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();t.run();//这里则是没有创建线程, 就是在主线程中执行上述 run 中的循环打印.while(true){System.out.println("hello main");try{Thread.sleep(1000);}catch (InterruptedException e) {e.printStackTrace();}}}
}

t.start() (Thread类中自带的方法):
调用 操作系统 提供的"创建线程" api,
在内核创建对应的 pcb 加入到链表中,
进一步的系统调度到这个线程了之后,
就会执行上述 run 方法中的逻辑.

当我们运行时, 只能看见起循环 Thread线程 内的打印操作, 而看不见 main线程 的打印操作.
此时的 run 和 主线程的循环是 串行执行, 不是 “并发执行”. 必须要求 run 中的循环结束, 才能继续执行到下一个循环.

像以上的 run, 定义好,而不去手动调用, 把这个方法交给系统/其他的库/其他框架调用.这样的方法称为: “回调函数”(callback function).

java数据结构, 谈到了比较强, 类似于 回调函数 的效果. PriorityQueue 优先级队列.

多线程 run 方法, 和上述两个情况本质一样, 都是回调函数.

Thread 第 2 种写法

package thread;
//Runnable: 描述一个任务
class MyRunnable implements Runnable{@Overridepublic void run() {while(true){System.out.println("hello thread");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}
}
public class Demo2 {public static void main(String[] args){Thread t = new Thread(new MyRunnable());t.start();while (true){System.out.println("hello main");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}
}

第一种写法, 是 Thread 自己记录自己的操作.
第二种写法, 是 Runnable 记录操作, Thread 负责执行.

当运行内容 与 执行 两个操作分离开, 实现了解耦合操作.
在java中 解耦合 使用接口实现.

解耦合的作用: 简单来讲, 就是使代码的维护难度降低.

Thread 第 3 种写法

package thread;public class Demo3 {public static void main(String[] args) {Thread t = new Thread(){/*这里的 new Thread 并非是 new 一个 Thread, 而是几个操作融合在了一起1. 创建了一个 Thread的子类(匿名的)2. 同时创建了一个该子类id实例, 对于匿名内部类只能创建这一个实例,这个实例创建完之后, 再也拿不到这个匿名内部类了.3. 此处的子类内部重写了父类 run 方法.*/@Overridepublic void run() {System.out.println("hello thread");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}};t.start();while(true){System.out.println("hello main");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}
}

Thread 第 4 种写法

package thread;public class Demo4 {public static void main(String[] args) {//Runnable 匿名内部类,//此处匿名内部类,只针对 Rnunable,与 Thread 无关//把 Runnable 实例, 作为参数传入到 Thread 的构造方法内Thread t = new Thread(new Runnable() {/*1.创建新的类, 实现Runnable.但类名是匿名的.2.同时创建了这个新类的实例(一次性)3.重写run方法*/@Overridepublic void run() {while(true){System.out.println("hello thread");try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}}});t.start();while(true){System.out.println("hello main");try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}}}

Thread 第 5 种写法

lambda 表达式

package thread;
//使用 lambda 表达式
public class Demo5 {public static void main(String[] args) {//此处的 lambda 就是要代替Demo4重写的 run方法Thread t = new Thread(() -> {System.out.println("hello Thread");try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}});t.start();while(true){System.out.println("hello main");try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}}
}

以上 5 种 方法,本质上都是
1.要把线程执行的任务内容表达出来.
2.通过 Thread 的 start 来创建/启动系统种的线程.
(Thread 对象和操作系统内核中的线程是 一 一 对 应 的关系)

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

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

相关文章

PVE虚拟机隐藏状态栏虚拟设备

虚拟机启动后,状态栏会出现一些虚拟设备,点击弹出会导致虚拟机无法使用。 解决方案: 1、在桌面新建disable_virtio_removale.bat文件,内容如下: ECHO OFF FOR /f %%A IN (reg query "HKLM\SYSTEM\CurrentContro…

【注释和反射】类加载的过程

继上一篇博客【注释和反射】获取class类实例的方法-CSDN博客 目录 三、类加载的过程 例子 三、类加载的过程 在Java虚拟机(JVM)中,类加载是一个将类的字节码文件从文件系统或其他来源加载到JVM的内存中,并将其转换为类或接口的…

JSON基础

JSON JavaScript Object Notation(js对象标记法) JSON定义 {"name":"Tom","age":20,"gender":"male" }JSON格式中的键必须使用双引号括上 因为其语法格式简单,层次结构鲜明,多作为数据载体在网络中进行数据传输 JSON定…

【语音识别】搭建本地的语音转文字系统:FunASR

参考自: 参考配置:FunASR/runtime/docs/SDK_advanced_guide_offline_zh.md at main alibaba-damo-academy/FunASR (github.com)参考配置:FunASR/runtime/quick_start_zh.md at 861147c7308b91068ffa02724fdf74ee623a909e alibaba-damo-aca…

猎聘爬虫(附源码)

废话不多说直接附源码 cookies需要替换成自己的 , 该网站在不登录的情况下只能请求到10页数据 , 想要获得完整数据需要携带登录后的cookies import requests import json from lxml import etree import os import openpyxlheaders {"Accept": "application/…

年如何在不丢失数据的情况下解锁锁定的 Android 手机?

当您忘记密码、PIN 码或图案并且想要解锁 Android 手机时,您可能会丢失 Android 手机上的数据。但您无需再担心,因为在这里,我们想出了几种解锁锁定的 Android 手机而不丢失数据的方法。 方法 1. 使用 Android Unlock 解锁锁定的 Android 且不…

Java中的异常和错误

Exception ArrayIndexOutOfBoundsException(数组下标越界) NullPionterException(空指针异常) ArithmeticException(算数异常) MissingResourceException(丢失资源) ClassNotFo…

记录一次WLAN Panic导致的gcore问题分析

记录一次WLAN Panic导致的gcore问题分析 背景 高通QA架构问题出现在几天前,测试同事大面积报出了开机后直接卡死的问题;经过初步分析,确认是进入了Guest Coredump(gcore) 分析 确认直接原因 解析gcore文件&#x…

信息收集分类

在信息收集中,需要收集的信息:目标主机的DNS信息、目标IP地址、子域名、旁站和C段、CMS类型、敏感目录、端口信息、操作系统版本、网站架构、漏洞信息、服务器与中间件信息、邮箱、人员、地址等。 信息收集区别 主动信息收集:直接与目标信息发…

mathtype设置公式编号,公式居中以及编号靠右

在word中实现: 1. 首先点击栏,选择更多栏去看 看到栏的宽度,然后去设置样式 在开始-样式中设置,新建样式: 新建样式,然后设置格式-制表位,选择对齐方式,居中对齐设置刚才的一半,右…

RK3568 学习笔记 : u-boot 千兆网络功能验证

前言 开发板型号: 【正点原子】 的 RK3568 开发板 使用 虚拟机 ubuntu 20.04 编译 RK3568 Linux SDK,生成镜像,烧写后,Linux 系统正常启动 开启后可以使用 CTRLC 进入 u-boot 本篇验证一下 u-boot 下网络功能 【正点原子】 rk…

MATLAB 运算符

MATLAB 运算符 运算符是一个符号,告诉编译器执行特定的数学或逻辑操作。MATLAB设计为主要在整个矩阵和数组上运行。因此,MATLAB中的运算符既可以处理标量数据,也可以处理非标量数据。MATLAB允许以下类型的基本运算- 算术运算符 关系运算符…

JavaScript:js基础1

JavaScript 一门跨平台,面向对象的脚本语言,来控制网页行文使网页可交互 JavaScript引入方式: <script>alert("Hello JS") </script>js语句必须在 <script>标签之间,在html文档中,可以在任意地方,放置任意数量的script 一般会把脚本置于 <…

Windows SMBGhost CVE-2020-0796 Elevate Privileges

SMBGhost CVE-2020-0796 Microsoft Windows 10 (1903/1909) - ‘SMBGhost’ SMB3.1.1 ‘SMB2_COMPRESSION_CAPABILITIES’ Local Privilege Escalation https://www.exploit-db.com/exploits/48267 Github https://github.com/danigargu/CVE-2020-0796 修改载荷[可选] 生成 c# …

【ARMv9 DSU-120 系列 -- Mapping for address target groups to CHI bus master ports】

文章目录 Mapping for address target groups to CHI bus master ports映射决定过程示例CHI id bit settingMapping for address target groups to CHI bus master ports 在DSU-120(DynamIQ™共享单元-120)中,地址目标组与总线主端口之间的映射关系是通过在复位时决定哪些总…

LLaMA Factory单机微调的实战教程

大家好,我是herosunly。985院校硕士毕业,现担任算法研究员一职,热衷于机器学习算法研究与应用。曾获得阿里云天池比赛第一名,CCF比赛第二名,科大讯飞比赛第三名。拥有多项发明专利。对机器学习和深度学习拥有自己独到的见解。曾经辅导过若干个非计算机专业的学生进入到算法…

23年HVV微b蓝初面经

1. 自我介绍 从项目经验 工作经历 个人技术 上面三个方面说一些就行 2. 平时学习的方式是什么&#xff0c;有没有系统学习过安全&#xff0c; web 、内网学的怎么样 学的 b 站系统的课程&#xff0c;加了很多学习圈子、论坛&#xff0c;内网只涉猎了一点&#xff0c;学习的不…

【JAVA基础之IO】字节流、字符流以及乱码问题

&#x1f525;作者主页&#xff1a;小林同学的学习笔录 &#x1f525;mysql专栏&#xff1a;小林同学的专栏 目录 1. IO概述 1.1 什么是IO 1.2 IO的分类 1.3 字节和字符流的顶级父类 2. 字节流 2.1 一切皆为字节 2.2 字节输出流【OutputStream】 2.3 FileOutputStream类…

【GUI软件】小红书关键词搜索结果批量采集

一、背景介绍 1.1 爬取目标 用python开发的爬虫采集软件&#xff0c;可自动按关键词抓取小红书笔记。 软件界面截图&#xff1a; 爬取结果截图&#xff1a; 结果截图1: 结果截图2: 结果截图3: 以上。 1.2 演示视频 软件运行演示&#xff1a; 【软件演示】小红书搜…

零信任网络安全技术雷达图3.0正式发布

伴随零信任理念的发展和实施&#xff0c;零信任技术体系的演进变革也日趋完善。易安联力图通过持续更新并优化零信任雷达图&#xff0c;以反映零信任技术在应对新型网络安全挑战中的创新和发展&#xff0c;为企业和组织提供前瞻性的技术建议&#xff0c;助力其构建更为强大和灵…