【JavaEE】认识线程

4c9c742f3a02521f400df47c0c39dd48.png


一、引入线程

在任务管理器界面可以看到很多进程,可以利用CPU多核心这一点来更有效的执行这些进程,即在处理过程中将CPU的多个时间片分配给每个进程,这样的 "多进程编程"就可以起到并发编程的效果,因为进程可以被调度到

虽然多进程编程可以解决进程多的问题,但也带来了一些麻烦

比如:一个服务器要给多个客户端提供服务,每当有一个客户端连上服务器,服务器就要创建一个进程给其提供服务,当客户端断开时,服务器就要销毁这个进程,那么问题就是如果有客户端频繁的连接、断开,服务器就要频繁的创建和销毁进程,这样的频繁操作会使服务器响应变慢

所以为了解决上述进程太"重量"的问题,就引入了线程(创建和销毁的开销较小)

二、线程(thread)

2.1 再谈PCB

线程可以理解为进程的一部分,一个进程可以包含一个线程或多个线程,上篇文章讲过PCB用来描述进程,实际上是一个PCB描述一个线程,多个PCB联合在一起描述了一个进程

针对PCB的那几个属性:

82304220c6a917bd24cc832c70002460.png

每一个线程都是独立在CPU上调度执行的,所以又称线程是系统调度的基本单位

2.2 为什么线程创建和销毁的开销比进程小?

在创建进程时,会涉及到资源分配和释放,而一个进程中的若干个线程是共享资源的,在创建线程时,此时进程已经创建好了,资源也分配好了,那么创建线程就省去了资源分配和释放的步骤,后续再创建线程就不必再申请资源

同一个进程包含N个线程,只有在创建第一个线程时(也是创建进程时)会进行资源申请操作,后续再创建线程时就不会在进行申请资源的操作了

三、多线程代码

Java提供了一个 Thread类 用来表示线程,在该类中有一个run方法,方法内容就是该线程要执行的任务,所以可以通过写一个类继承Thread并重写run方法,这样就可以自己设定线程要完成的任务

class MyThread extends Thread {@Overridepublic void run() {System.out.println("hello thread");}
}public class Demo1 {public static void main(String[] args) {Thread t = new MyThread();}
}

run方法只是描述了线程要完成的任务,并没有创建线程,此时就需要调用start方法,通过start方法调用操作系统的提供的"创建线程"api,在内核中创建对应的pcb,在系统调度到这个线程时,就会执行run方法中的逻辑

(run方法不是被start调用的,而是在start创建出来的线程,在线程里被系统调用的)

class MyThread extends Thread {@Overridepublic void run() {System.out.println("hello thread");}
}public class Demo1 {public static void main(String[] args) {Thread t = new MyThread();t.start();  //打印出 hello thread}
}

多个线程之间的执行顺序是无序的

在上述代码中,有两个线程:1.t 线程,2. main方法所在的线程(主线程),给出下面一段代码

class MyThread extends Thread {public void run() {while (true) {try {Thread.sleep(1000); //sleep是让该线程主动处于阻塞状态1s,即代码在此处等待1s,不继续往下执行,由于该方法会抛出异常,所以用try-catch结构进行处理} catch (InterruptedException e) {throw new RuntimeException(e);}System.out.println("hello thread");}}
}
public class Demo {public static void main(String[] args) throws InterruptedException {Thread t = new MyThread();t.start();while (true) {Thread.sleep(1000);System.out.println("hello main");}}
}

该代码的执行结果为:

ebb3197189140e020785a28889befcdd.png

main线程和t线程并发执行,main线程和t线程的打印都在执行,且每次循环谁先执行的顺序不一定,所以称多个线程之间的执行顺序是无序的

3.1 5种创建线程的方法

1.上述的创建Thread子类并重写run方法就是其中一种

2.通过实现Runnable接口创建线程

Runnable接口:

3d208a5cc226a4a21cf44faca532881c.png

在该接口中只有run方法,run方法用来描述线程要做的事情

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

上述的Thread t = new Thread(new MyRunnable());这样写可以解耦合,Thread没有记录任务内容,它只负责执行,任务内容由Runnable记录,这样就将任务和执行分开了,未来改用其他方式执行这些任务的改动成本较低

3.针对1的变形,使用匿名内部类,继承Thread并重写run方法

public class Test {public static void main(String[] args) {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);}}}};t.start();}
}

使用匿名内部类的具体步骤如下:

1)创建一个Thread的子类,该类的名字匿名

2)创建子类的同时又创建这个子类的实例

3)最后重写run方法

4.针对Runnable的匿名内部类

Thread t = new Thread(new Runnable() {@Overridepublic void run() {...}
});

此处的匿名内部类只针对Runnable,和Thread没有关系,只是把Runnable的实例作为参数传入到Thread的构造方法中

5.使用lambda表达式

Thread t2 = new Thread(() -> {//在这里直接写线程所要执行的任务,也就是run方法中的内容
});

总结:上述5种写法本质上就是2点:1.把线程要执行的任务内容表示出来,2.通过Thread的start方法来创建/启动系统中的线程


🙉本篇文章到此结束,之后会继续探究多线程的内容

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

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

相关文章

qt QStatusBar详解

1、概述 QStatusBar是Qt框架提供的一个小部件,用于在应用程序窗口底部显示状态信息。它可以显示一些固定的文本和图标,并且可以通过API动态更新显示内容。QStatusBar通常是一个水平的窗口部件,能够显示多行文本内容,非常适合用于…

【Ubuntu】ubuntu 22.04 设置 Xorg 弃用 Wayland

# 编辑gdm3配置文件 sudo vim /etc/gdm3/custom.conf # 重启gdm3 sudo systemctl restart gdm3方式一:如果进行上述操作后,有对比度严重错误问题,请执行下列命令 # 安装驱动 sudo ubuntu-drivers autoinstall 方式二:推荐尝试方式…

日语学习的难易程度

日语学习的难易程度是一个相对主观的问题,它受到多种因素的影响,包括个人的语言学习能力、学习方法、学习时间、学习资源的可获得性以及个人对日语文化的兴趣和投入程度等。以下是对日语学习难易程度的一些分析: 优点与易学之处 文字系统&am…

WPF 打包

打包为单个exe文件直接运行 - - -版本.NET8 新建WPF项目 右键 - 发布 选择发布文件夹 选择发布文件夹 选择发布文件夹 配置 配置,保存 发布 WPF 打包为exe安装程序 示例 实现思路 引导项目中嵌入其它项目可运行目录的zip引导项目中解压zip文件到指定文件夹是…

RTC精度及校准

RTC精度偏差: RTC的基准时间和精度与石英晶体的频率相关,晶体的谐振频率取决于温度,因此RTC性能与温度相关,晶体的频率偏差是晶体正常频率的温度反转函数。 一、硬件方面: 1.使用高精度振荡器的RTC模块; …

C++ Qt6 QtQuick/QML入门进阶与项目实战视频教程

课程介绍 C Qt这些年在PC客户端、嵌入式、汽车座舱仪表等领域应用很广泛,例如剪映专业版、微信4.0、亿图脑图、Steam、美图秀秀、腾讯会议、钉钉(部分模块)等都是使用C QWidget/QML开发。特别是QML这种声明式UI开发更加快捷,QML的界面开发效率相对于QWid…

Linux:防火墙和selinux对服务的影响

1-1selinux 1-1 SELinux是对程序、文件等权限设置依据的一个内核模块。由于启动网络服务的也是程序,因此刚好也 是能够控制网络服务能否访问系统资源的一道关卡。 1-2 SELinux是通过MAC的方式来控制管理进程,它控制的主体是进程,而目标则是…

逻辑回归处理非线性关系与支持向量机的性能对比

逻辑回归是一种常用的线性分类方法,通常用于处理线性关系的二分类任务。但是,对于非线性问题,传统的逻辑回归模型可能表现不佳,因为它假设数据可以被一个线性决策边界分割开来。为了使逻辑回归能够处理非线性关系,我们…

2021数二第9题 线代 一个方程组的解是另一个方程组的解

题目展示的是一个方程组的列向量 可由另一个列向量表示所以是矩阵的转置

C#与C++交互开发系列(二十):跨进程通信之共享内存(Shared Memory)

1、前言 共享内存(Shared Memory)是一种高效的跨进程通信方式,尤其适用于同一台计算机上的进程之间的高速数据传输。与套接字相比,共享内存允许多个进程直接访问同一块内存区域,减少了数据传输的中间步骤,…

防火墙|WAF|漏洞|网络安全

防火墙|WAF|漏洞|网络安全 防火墙 根据内容分析数据包: 1、源IP和目的IP地址 2、有效负载中的内容。 3、数据包协议(例如,连接是否使用 TCP/IP 协议)。 4、应用协议(HTTP、Telnet、FTP、DNS、SSH 等)。 5…

web——warmup——攻防世界

这道题还是没有做出来。。,来总结一下 1.ctrlU显示源码 2.看见body里有source.php 打开这个source.php 看见了源码 highlight_file(FILE); 这行代码用于高亮显示当前文件的源码,适合调试和学习,但在生产环境中通常不需要。 class emmm 定义…

HTML第一次作业

制作带有下拉悬停菜单的导航栏 <!DOCTYPE html> <html> <head><meta charset"utf-8"><title>带有下拉悬停菜单的导航栏</title><style>* {margin: 0;padding: 0;}#menu {background-color: blue;width: 100%;height: 50p…

数据结构 C/C++(实验三:队列)

&#xff08;大家好&#xff0c;今天分享的是数据结构的相关知识&#xff0c;大家可以在评论区进行互动答疑哦~加油&#xff01;&#x1f495;&#xff09; 目录 提要&#xff1a;实验题目 一、实验目的 二、实验内容及要求 三、算法思想 实验1 实验2 四、源程序及注释…

Chromium127编译指南 Mac篇(二)- 安装Xcode

1. 概述 在Chromium开发的道路上&#xff0c;为Mac平台搭建正确的环境是至关重要的第一步。本文将聚焦于Xcode的安装过程&#xff0c;它作为Mac上不可或缺的开发工具&#xff0c;为Chromium的编译提供了必要的编译器和工具链。 我们将详细解析如何选择、下载并安装适合Chromium…

移动应用开发 实验二:标准身高计算器

文章目录 准备工作一&#xff0c;创建Android Studio项目二&#xff0c;创建活动模块三&#xff0c;设计用户界面&#xff08;一&#xff09;设置页面布局&#xff08;二&#xff09;添加标题文本控件&#xff08;三&#xff09;设计体重输入框&#xff08;四&#xff09;设计性…

这个超级棒,我收藏的样机素材,统统分享给你们

Hello&#xff0c;大家好&#xff0c;我是后期圈&#xff01;工作不息摸鱼不止&#xff01;继续给圈友们带来有趣好玩的推荐&#xff0c;圈友们在摸鱼的同时别忘记多多点赞支持一波呀 今天给大家分享 4个超实用效率高质量网站&#xff0c;请各位偷偷收藏使用&#xff0c;懂得都…

管理 Elasticsearch 变得更容易了,非常容易!

作者&#xff1a;来自 Elastic Ken Exner Elasticsearch 用户&#xff0c;我们听到了你的心声。管理 Elasticsearch 有时会变得很复杂&#xff0c;面临的挑战包括性能调整、问题检测和资源优化。我们一直致力于简化你的体验。今天&#xff0c;我们宣布了自收购 Opster 以来的一…

spark-本地模式的配置和简单使用

python环境的安装 在虚拟机中&#xff0c;只能安装一个python的版本&#xff0c;若想要安装别的版本&#xff0c;则需要卸载之前的版本——解决方式&#xff0c;安装Anaconda 通过百度网盘分享的文件&#xff1a;Anaconda3-2021.05-Linux-x86_64.sh 链接&#xff1a;https://…

将vscode的终端改为cygwin terminal

现在终端是默认的power shell&#xff0c;没有显示cygwin 接下来选择默认配置文件 找到cygwin的选项即可 然后提示可能不安全什么的&#xff0c;点是&#xff0c;就有了