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

Javaee---多线程(一)

在这里插入图片描述

文章目录

  • 1.线程的概念
  • 2.休眠里面的异常处理
  • 3.实现runnable接口
  • 4.匿名内部类子类创建线程
  • 5.匿名内部类接口创建线程
  • 6.基于lambda表达式进行线程创建
  • 7.关于Thread的其他的使用方法
    • 7.1线程的名字
    • 7.2设置为前台线程
    • 7.3判断线程是否存活
  • 8.创建线程方法总结
  • 9.start方法
  • 10.终止(中断)线程-interrupt
    • 10.1自定义标志位
    • 10.2使用系统里面的标志位
  • 11.线程等待join
  • 12.线程方法总结
  • 11.线程等待join
  • 12.线程方法总结

1.线程的概念

(下面的这个图片里面的代码有错误,我们new的这个mythread类的对象,应该是使用这个Thread这个类进行接收,这个是个向上转型的过程);

  • 我们的这个里面使用到了这个thread类,但是不需要进行这个import的操作,这个主要就是因为我们的这个Thread是位于这个java.lang这个包下面的;像我们之前使用的这个String也是在这个包下面,我们也没有进行这个import的操作;
  • 这个Thread里面是有这个run方法的,我们的这个mythread类里面对于这个夫类里面的方法进行了重写;
  • 我们的main方法里面执行这个start时候,就会进入这个run入口进而对于这个内容进行打印输出;

image-20241019192827539

实际上打印输出的时候main方法里面的内容和我们的自定义类里面的这个内容是独立进行的,两个并不会相互依赖;每一个线程都是一个独立的执行流;

image-20241019211712898

当我们把这个start修改为这个run之后,这个就会先去执行我们自己的自定义类里面的这个重写的run方法,这个执行完成之后才会继续执行这个下面的helli main打印输出,但是因为我们的这个是死循环,因此这个会一直打印输出我们的hello thread;

image-20241019211737878

2.休眠里面的异常处理

为了更加清楚的看到这个打印的效果,我们可以对于这个程序进行休眠操作,就是使用这个sleep方法,但是这个方法在进行使用的时候可能会出现一些问题,就是异常情况,针对于自定义类和main方法里面的异常,我们的处理手段是不一样的:

下面的这个异常是受查异常,需要进行显示处理:要么throws,要么try-catch

重写父类的方法,父类的方法里面没有throws,因此我们不可以throws;

image-20241020212336753

image-20241020212513823

相比之下,在这个main里面的这个内容都是我们自己写的,因此这个时候我们就可以使用这个throws方法对于这个出现的异常进行抛出;

image-20241020213545037

有了上面的两个休眠的操作,这个时候我们重新运行这个程序,这个时候就会发现这个两个语句的打印输出的速度就变慢了,但是这个出现的先后顺序其实并不是确定的,这个主要取决于我们的操作系统对于这个线程的调度(调度器)的具体实现,因此我们可以看到有的时候是这个hello thread先打印输出,但是有的时候是这个hello main先打印输出;

3.实现runnable接口

下面的这个就是实现我们的这个runnable接口的方式,两个类里面的这个异常的处理方式还是一样的,一个是捕捉异常,一个就是抛出异常;

但是在这个主方法里面,我们使用这个已有的MyRunnable类实例化对象,相当于是定义了一个任务,然后我们吧这个传递到我们的这个new Thread这个参数里面去,相当于就是使用这个Thread去执行这个任务,其他的和上面的这个方式是没有任何区别的;

针对于这个方式,实现了这个runnable接口的这个类的实例化对象作为我们的这个Thread接口的构造方法的参数,这个和上面最大的不同就是解耦合:耦合指的就是我们的一个程序里面的不同模块之间的影响的程序,解耦合就是解除不同的模块之间的相互的影响;

这样的解耦合的好处就是我们只是定义了这个任务,但是交给谁去执行这个任务就没那么重要了,这个就是这个实现接口的方式和上面的最大不同;
在这里插入图片描述

4.匿名内部类子类创建线程

public class Test {public static void main(String[] args) throws InterruptedException {//匿名内部类,不知道这个类叫什么,但是知道这个类是我们的Thread的子类//不知道这个类的名字也不重要,因为这个类我们只会使用一次//下面的这个new后面的这个其实就可以理解为是一个类,使用这个没有名字的类实例化对象,在这个匿名的类里面对于这个方法进行重写,里面的这个对于异常的处理和定义两个类的时候是一样的;Thread t = new Thread(){@Overridepublic void run() {while(true){System.out.println("hello thread!");try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}}};//使用我们创建的这个线程去开始这个线程的执行,start就是这个线程执行的入口t.start();while(true){System.out.println("hello main!");Thread.sleep(1000);}}
}

5.匿名内部类接口创建线程

public class Test {public static void main(String[] args) throws InterruptedException {//匿名内部类,不知道这个类叫什么,但是知道这个类是我们的Thread的子类//不知道这个类的名字也不重要,因为这个类我们只会使用一次//下面的这个就是我们不知道这个类叫什么名字,但是这个类实现了这个接口Runnable//因此在这个匿名内部类里面对于这个接口里面的方法进行了重写Runnable runnable = new Runnable() {@Overridepublic void run() {while(true){System.out.println("hello thread!");try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}}};//这个就是我们的这个实现接口的类的实例化对象作为一个参数进行传递Thread t=new Thread(runnable);t.start();while(true){System.out.println("hello main!");Thread.sleep(1000);}}
}

6.基于lambda表达式进行线程创建

lambda实际上是这个匿名内部类的一个简化的方式:本质上就是一个函数表达式

public class test {public static void main(String[] args) throws InterruptedException {//lambda表达式是一个匿名函数,主要是实现回调函数的效果//回调函数是计算机里面的一个很重要的术语//回调函数--函数指针:函数指针实现转移表,减少if-else分支数目//使用函数指针作为回调函数--实现qsort()的比较//其实这个lambda表达式并不是很复杂,形式上就是这个()->{},我们的这个相关的代码就是写在这个大括号			里面的Thread t = new Thread(()->{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!");Thread.sleep(1000);}}
}

7.关于Thread的其他的使用方法

上面我们介绍两个:

1.直接调用无参数的,就是我们最开始介绍的;

2.传递的参数是我们的实现接口的类的实例化对象;

除此之外,我们还可以传递name参数,给这个线程起名字,对于线程进行区分:

7.1线程的名字

public class Test {public static void main(String[] args) {//String name;Thread t = new Thread(() -> {while(true){System.out.println("hello thread!");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}},"这个是新的线程" );//上面的这个就是相当于是在原来的这个表达式的后面多了这个name属性,这样我们使用这个jconsole工具			进行查看的时候,我们就可以看到自己对于这个线程的命名了;t.start();}
}

7.2设置为前台线程

还是上面的这个程序,其实在这个默认的情况下,这个线程就是前台线程,就是我们的这个线程不结束,这个程序就不会结束,但是我们的后台线程就是这个线程结束与否,对于我们的整个程序的结束没有影响;

这个默认情况下是前台线程,我们可以使用这个setDaemon方法把这个线程设置为后台的线程;

我们的这个具体的差别可以在打印的时候看出来,就是我们的这个内容好像没有进行打印,这个程序就结束了;

public class Test {public static void main(String[] args) {//String name;Thread t = new Thread(() -> {while(true){System.out.println("hello thread!");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}},"这个是新的线程" );//设置为后台的线程,运行起来就不会进行打印t.setDaemon(true);t.start();}
}

7.3判断线程是否存活

这个就是使用的t.isAlive方法判断这个线程是不是存活的,下面的这个使用start开始的时候,就是存活的线程,打印输出的结果就是true,但是休眠之后,这个就是死亡的,打印输出false;

public class Test {public static void main(String[] args) throws InterruptedException {Thread t = new Thread(()->{System.out.println("线程开始");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("线程结束");});t.start();System.out.println(t.isAlive());Thread.sleep(2000);System.out.println(t.isAlive());}
}

8.创建线程方法总结

image-20241021125053812

9.start方法

start和run方法的区别:

我们的start方法会去调用这个系统里面的api,进行线程的创建;

run只会去执行这个线程里面的内容(会在这个start创建线程之后自动被调用);

两个的本质区别就是是不是调用了这个系统里面的api,创建出来了新的线程;

10.终止(中断)线程-interrupt

10.1自定义标志位

需要注意的就是这个自定义的静态的变量需要是全局的,不可以是局部的,因为这个lambda是变量的捕捉,这个变量需要是这个final或者是视为这个final的变量;

我们的这个变量一旦写作这个局部的,这个时候我们下面不可以进行修改了,但是我们的有修改,所以写成局部的就会报错,大家可以自己去尝试一下,看看这个效果,这个主要是lambda的语法导致的;

image-20241021132639605

10.2使用系统里面的标志位

为什么会有下面的这个,因为上面的存在缺陷,就是我们需要手动创建,而且我们的线程如果正在休眠,我们把这个标志位修改掉,这个线程无法及时的做出回应,或者是叫做响应;

但是如果我们使用这个系统里面的标志位,这个就是currentThread().isInterrupted()方法进行判断当前的这个线程是不是被打断了;

我们的这个里面有一个t.sleep()这个方法就是进行线程的唤醒,上面的这个手动创建标志位的方法,如果我们的这个线程在休眠,这个时候不可以及时的进行响应,但是我们的这个interrupt这个方法,就会触发这个线程的异常,让这个休眠的线程提前被唤醒,但是我们在运行的时候会发现这个会抛出异常之后,还是会继续执行的;

这个主要原因就是我们的interrupt唤醒这个线程之后,我们的异常抛出把这个设置的标志位清除掉了,就是我们的自动设置的标志位没有了效果,我们的异常让这个标志位的效果失效了,接下来,线程可以自己决定接下来如何进行处理;

image-20241021174301710

11.线程等待join

下面的这个程序就是我们的t线程会休眠,我们的t.join就会让这个主线程等待我们的t线程,直到我们的t线程执行结束,主线程才会结束;

image-20241021181517994

12.线程方法总结

image-20241021183414460
动设置的标志位没有了效果,我们的异常让这个标志位的效果失效了,接下来,线程可以自己决定接下来如何进行处理;

在这里插入图片描述

11.线程等待join

下面的这个程序就是我们的t线程会休眠,我们的t.join就会让这个主线程等待我们的t线程,直到我们的t线程执行结束,主线程才会结束;

在这里插入图片描述

12.线程方法总结

在这里插入图片描述

相关文章:

Javaee---多线程(一)

文章目录 1.线程的概念2.休眠里面的异常处理3.实现runnable接口4.匿名内部类子类创建线程5.匿名内部类接口创建线程6.基于lambda表达式进行线程创建7.关于Thread的其他的使用方法7.1线程的名字7.2设置为前台线程7.3判断线程是否存活 8.创建线程方法总结9.start方法10.终止&…...

Java后端面试内容总结

先讲项目背景,再讲技术栈模块划分, 讲业务的时候可以先讲一般再特殊 为什么用这个,好处是什么,应用场景 Debug发现问题/日志发现问题. QPS TPS 项目单元测试,代码的变更覆盖率达到80%,项目的复用性高…...

DC-1渗透测试

DC1 五个flag的拿取(截图是五个flag里面的内容) 注意事项:kali的用户名:root 密码:kali 注意:DC1 只要开机服务就起来了 思路:信息收集—> 寻找漏洞—> 利用漏洞(sql注入,文件上传漏洞…...

深度剖析:电商 API 接口如何成就卓越用户体验

在电商领域的激烈竞争中,提供卓越的用户体验已成为企业脱颖而出的关键。而电商 API 接口在其中扮演着举足轻重的角色,它如同电商平台的神经系统,连接着各个关键环节,为用户带来无缝、高效且个性化的购物之旅。 一、极速响应&#…...

C++调试经验:Ubuntu下CMake链接常见库的方式(持续更新)

目录 1. CMake链接OpenCV库 2. CMake链接VTK库 3. CMake链接Qt库 4. CMake链接PCL库 5. CMake链接Gstreamer 6. CMake链接json-cpp库 7. CMake链接yaml-cpp库 8. CMake链接breakpad库 9. CMake链接Eigen3库 1. CMake链接OpenCV库 find_package (OpenCV 4 REQUIRED)…...

【HarmonyOS】应用实现APP国际化多语言切换

【HarmonyOS】应用实现APP国际化多语言切换 前言 在鸿蒙中应用国际化处理,与Android和IOS基本一致,都是通过JSON配置不同的语言文本内容。在UI展示时,使用JSON配置的字段key进行调用,系统选择对应语言文本内容。 跟随系统多语言…...

使用pandas进行数据分析

文章目录 1.pandas的特点2.Series2.1新建Seriws2.2使用标签来选择数据2.3 通过指定位置选择数据2.4 使用布尔值选择数据2.5 其他操作2.5.1 修改数据2.5.2 统计操作2.5.3 缺失数据处理 3.DataFrame3.1 新建 DataFrame3.2 选择数据3.2.1 使用标签选择数据3.2.2 使用 iloc 选择数据…...

用于无监督域适应的提示分布对齐

论文探讨了视觉语言模型(VLMs)及其在无监督域适应(UDA)中的应用,并引入了一种名为提示分布对齐(Prompt-based Distribution Alignment,PDA)的方法,该方法采用双分支训练策…...

Rust整合Elasticsearch

Elasticsearch是什么 Lucene:Java实现的搜索引擎类库 易扩展高性能仅限Java开发不支持水平扩展 Elasticsearch:基于Lucene开发的分布式搜索和分析引擎 支持分布式、水平扩展提高RestfulAPI,可被任何语言调用 Elastic Stack是什么 ELK&a…...

Linux 文件权限管理:chown、chgrp 和 chmod 的使用及权限掩码规则

目录 文件权限的基本概念 chown:更改文件的拥有者 使用方法 示例 选项 chgrp:更改文件的所属组 使用方法 示例 chmod:更改文件的权限 使用方法 权限表示 选项 权限掩码(umask)规则 如何查看和设置 umask…...

简单记录ios打包流程

1、点击这里获取UDID 2、xcode登录开发者账户、确定唯一id(Bundle ID) 3、去这里注册appid 4、在这里这里创建app 5、之后xcode中打包...

右键以vscode打开目录的时候出现找不到应用程序

出现这个问题的主要原因,大概率可能是因为你移动了vscode的安装路径导致的。 解决办法 打开注册表:通过cmd 打开regedit 然后搜索:计算机\HKEY_CLASSES_ROOT\Directory\Background\shell 这个两个参数可以自己比对一下,主要需要检…...

【Go-Taskflow:一个类似任务流的有向无环图(DAG)任务执行框架,集成了可视化和性能分析工具,旨在简化并行任务的复杂依赖管理】

Go-Taskflow是一个静态有向无环图(DAG)任务计算框架,它受到taskflow-cpp的启发,结合了Go语言的原生能力和简洁性,特别适合于并发任务中复杂的依赖管理。 Go-Taskflow的主要特点包括: 高可扩展性&#xff1…...

排查PHP服务器CPU占用率高的问题

排查PHP服务器CPU占用率高的问题通常可以通过以下步骤进行: 使用top或htop命令:这些命令可以实时显示服务器上各个进程的CPU和内存使用情况。找到CPU使用率高的进程。 查看进程日志:如果PHP-FPM或Apache等服务器进程的日志记录了具体的请求…...

【学术会议论文投稿】“从零到一:使用IntelliJ IDEA打造你的梦幻HTML项目“

【JPCS独立出版】2024年工业机器人与先进制造技术国际学术会议(IRAMT 2024)_艾思科蓝_学术一站式服务平台 更多学术会议请看 学术会议-学术交流征稿-学术会议在线-艾思科蓝 目录 引言:为何选择IntelliJ IDEA? 第一步&#xff1a…...

Win11安装基于WSL2的Ubuntu

1. 概述 趁着还没有完全忘记,详细记录一下在Win11下安装基于WSL2的Ubuntu的详细过程。不得不说WSL2现在被微软开发的比较强大了,还是很值得安装和使用的,笔者就通过WSL2安装的Ubuntu成功搭建了ROS环境。 2. 详论 2.1 子系统安装 在Win11搜…...

如何对pdf文件进行加密?pdf文件加密全攻略与深度解析(5个方法)

如何对pdf文件进行加密? 只见,在深夜的情报局里,特工小李将一份绝密PDF文件放在保险箱内,以为这样就天衣无缝了。 细细推敲,漏洞百出: 如果钥匙被盗呢?如果被神匠破解出密码呢?如果…...

c++面向对象三大特性之一-----多态

前言:本文将介绍在32位平台下,c的多态,通过本篇文章的学习你讲了解多态的原理,多态的底层还有一些不常见的关键字的介绍(final,override). 文章内容如下: 1:多态的概念 2:多态的定义与实现 3:多态的原理 4:抽象类 文章正式开始 1:多态的概念 多…...

8.Linux按键驱动-中断下半部

1.编程思路 1.1在gpio结构体中添加tasklet_struct结构体 1.2在probe函数中初始化tasklet结构体 1.3在中断服务程序中调度tasklet 1.4在这个函数中执行其它任务 2.代码: 应用程序和Makefile和上节一致 https://blog.csdn.net/weixin_40933496/article/details/1…...

Redis 线程控制 总结

前言 相关系列 《Redis & 目录》(持续更新)《Redis & 线程控制 & 源码》(学习过程/多有漏误/仅作参考/不再更新)《Redis & 线程控制 & 总结》(学习总结/最新最准/持续更新)《Redis &a…...

测试微信模版消息推送

进入“开发接口管理”--“公众平台测试账号”,无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。 获取access_token: 自定义模版消息: 关注测试号:扫二维码关注测试号。 发送模版消息: import requests da…...

Java 语言特性(面试系列2)

一、SQL 基础 1. 复杂查询 (1)连接查询(JOIN) 内连接(INNER JOIN):返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...

【解密LSTM、GRU如何解决传统RNN梯度消失问题】

解密LSTM与GRU:如何让RNN变得更聪明? 在深度学习的世界里,循环神经网络(RNN)以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而,传统RNN存在的一个严重问题——梯度消失&#…...

Opencv中的addweighted函数

一.addweighted函数作用 addweighted()是OpenCV库中用于图像处理的函数,主要功能是将两个输入图像(尺寸和类型相同)按照指定的权重进行加权叠加(图像融合),并添加一个标量值&#x…...

python爬虫:Newspaper3k 的详细使用(好用的新闻网站文章抓取和解析的Python库)

更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Newspaper3k 概述1.1 Newspaper3k 介绍1.2 主要功能1.3 典型应用场景1.4 安装二、基本用法2.2 提取单篇文章的内容2.2 处理多篇文档三、高级选项3.1 自定义配置3.2 分析文章情感四、实战案例4.1 构建新闻摘要聚合器…...

解决本地部署 SmolVLM2 大语言模型运行 flash-attn 报错

出现的问题 安装 flash-attn 会一直卡在 build 那一步或者运行报错 解决办法 是因为你安装的 flash-attn 版本没有对应上,所以报错,到 https://github.com/Dao-AILab/flash-attention/releases 下载对应版本,cu、torch、cp 的版本一定要对…...

c#开发AI模型对话

AI模型 前面已经介绍了一般AI模型本地部署,直接调用现成的模型数据。这里主要讲述讲接口集成到我们自己的程序中使用方式。 微软提供了ML.NET来开发和使用AI模型,但是目前国内可能使用不多,至少实践例子很少看见。开发训练模型就不介绍了&am…...

成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战

在现代战争中,电磁频谱已成为继陆、海、空、天之后的 “第五维战场”,雷达作为电磁频谱领域的关键装备,其干扰与抗干扰能力的较量,直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器,凭借数字射…...

OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()

操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 在 GPU 上对图像执行 均值漂移滤波(Mean Shift Filtering),用于图像分割或平滑处理。 该函数将输入图像中的…...

rnn判断string中第一次出现a的下标

# coding:utf8 import torch import torch.nn as nn import numpy as np import random import json""" 基于pytorch的网络编写 实现一个RNN网络完成多分类任务 判断字符 a 第一次出现在字符串中的位置 """class TorchModel(nn.Module):def __in…...