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

多线程(一)

OKK,今天我们正式来学习多线程一这板块,这一板块内容繁杂,冗长,我们将通过很多期来对其进行介绍讲解

 一 . 认识线程 

(1)线程的概念 

线程是什么呢?一个线程就是一个 “ 执行流 ” ,每个线程之间都可以按照顺序执行自己的代码,多个线程之间 “ 同时 ” 执行着多份代码。我来给大家举个例子帮助大家更生动形象地理解 “ 线程 ”

例如:当我们过年的时候,我们就会吃饺子,要吃饺子呢,我们就需要包饺子(不知道各位平时是怎样吃饺子的啊,我们家一般都是自己包),包饺子就涉及到三个基本的步骤,要饺子皮儿,饺子馅,最后包饺子,如果我们想要包100个,200个饺子,那么我们一个人包就需要很多时间,并且可能在三个过程中不断地往返,导致我们效率低下,这就相当于单线程

那么这个时候,我们最合适的做法就是,叫爸爸妈妈和家里人来一起,每个人分配一项工作,例如妈妈负责擀面皮,我负责拌饺子馅,爸爸负责包饺子,通过这样的协同作业,我们的效率就会高很多,这就相当于。

将一个大任务分解成不同的小任务,交给不同执行流分别排队执行,这个过程我们就叫做多线程。而在这一过程中,因为本来是由我一个人的工作,我叫来了爸爸妈妈帮我分担,所以我就是主线程(Main Thread)。

(2)为什么要有线程 

为什么出现 “ 线程 ” 这一概念呢?首当其冲的就是因为我们的 “ 并发编程 ” 成为 “ 刚需 ”。那么这句话又抛出一个问题:

什么是并发编程呢?上一期提到,咱们计算机的 CPU 是有多个核心的(一般来说昂,现在的电脑应该普遍是多核的了)。那么咱们之前写到过的所有代码,在运行时都是只能使用 “ 一个核心 ”,此时,无论我们再如何优化代码,最多也只能做到使用一个 CPU 核心,就算我们这个核心已经跑满了,其余核心也是空闲的。而为了解决这一问题,通过写特殊的代码,我们就能够把多个 CPU 核心都利用起来,这样的代码就称之为 “ 并发编程 ”。

多进程编程就是一种典型的并发编程

虽然我们的多进程能够在一定程度上解决问题,但是随着我们的科技发展,电脑的普及率提高是吧,咱们的需求也变高了,对效率的要求也跟着越来越高了,这个时候,我们就追求更加高效的方式来实现并发编程。

多进程编程,最大的问题就是进程 “ 太重 ”,创建进程和销毁进程对时间和空间的开销较大,对于这个我们一般感受不到,但是一旦我们计算机运行的需求场景,需要非常频繁的创建销毁进程,那么这一开销就十分明显了。那么为了解决这一问题,更高效的实现并发编程呢,咱们的线程就应运而生了。

虽然多进程能够实现并发编程,但是为了解决进程开销较大的问题,咱们线程(Thread)这一概念诞生了,线程我们可以理解为更轻的进程,线程同样能解决并发编程的问题,但是其创建和销毁线程的开销比进程要小得多。因此,多线程的编程,就成为了当下主流的并发编程方式。

(3)进程与线程 

 进程跟线程的区别:

1 . 1 创建线程比创建进程更快;销毁线程比销毁进程更快;调度线程比调度进程更快。

1 . 2 进程是包含线程的,一个进程可以有多个线程,而每个进程至少包含一个线程,即主线程。

1 . 3 进程与进程之间不共享内存空间,而同一个进程的线程之间,共享同一个内存空间(内存,硬盘,网络宽带等)。

1 . 4 进程是系统分配的最小单位,线程是系统调度的最小单位。

1 . 5 一个进程挂了一般不会影响到其他程序,这一点我们称之为 “ 进程的隔离性 ”,(例如我们在玩游戏的时候,程序未响应,我们只是这个游戏这一个程序崩溃了,并不影响我们操作电脑运行其他程序,不会让我们的电脑整个死机)但是一个线程挂了,可能把同一个进程内的其他线程一起带走,整个进程都可能崩溃(比如我们在访问某一个网页的时候,这一个网页卡死了,未响应,但是我们此时要结束运行就必须关闭这一浏览器的所有网页)。

(4)Java 线程和操作系统线程的关系 

线程是操作系统中的概念,操作系统内核实现了线程这样的机制,并且对用户层提供了一些 API 供用户使用(例如 Linux 的 pthread 库)。

在 Java 标准库中 Thread 类可以视为是对操作系统提供的 API 进行了进一步的抽象与包装

 二 . 创建线程 

创建线程有很多种方式,这里为大家列举 5 个常用的方式:

 创建线程的常见方式:

(1)直接继承 Thread 类 

当我们在运行代码时我们会发现,打印结果是一会儿打印 “ hello main ” ,一会儿又打印 “ hello thread ” 这是因为我们线程在执行时有一个很显著的特点:“ 随机调度,抢占式执行 ”

(2)实现 Runnable 接口 

(3)使用匿名内部类创建 Thread 子类对象

(4)使用匿名内部类创建 Runnable 子类对象

(5)lambda 表达式创建 Runnable 子类对象

这最后一种用 lambda 表达式来实现,是我认为最简单,也是我最常用的一种昂。

 三 . 启动线程 

线程被创建出来,创建成功了,并不代表线程就开始运行了。

我们通过 调用 start()方法 ,这才真正的在操作系统的底层创建出了一个线程并开始运行。

 四 . 中断线程 

目前我们常见的中断线程的方式有两种:

(1)通过自定义变量来作为标志位,两个线程通过共享标志来进行沟通 

(2)调用 Interrupt()方法来通知 

这一个 Interrupt 方法给了我们更多的操作空间,并不是说直接强制中断我们的线程,而是我们可以通过自己手动是不结束,还是立即结束,还是等我们其他的代码逻辑完成之后再结束:

如同我们上方代码中的 catch 代码块中,我们如果不想结束,就什么都不写;如果想立刻结束就写上 catch 或 return;如果想稍后结束,我们就可以在 catch 代码块中添加其他的逻辑代码,例如释放一些资源,清理一些数据,提交结果等等,我们则会将这一块运行完之后再结束。

注: Interrupt 方法既能够设置标志位,也能唤醒 sleep 等阻塞方法

 五 . 等待线程 

我们通过调用 join()方法来实现线程的等待,例如:我们在 main方法中写上代码:t1.join(),这就表示,我们 t1 线程必须等待主线程(main)执行完后再执行(注:谁调用谁等)

 六 . Thread 类及常见方法 

Thread 类是 JVM 用来管理线程的一个类,换句话说,每个线程都有一个唯一的 Thread 对象与之关联。

(1)Thread 的常见构造方法 

其中,Thread(String name)适用于给线程取名字的,如果我们不设置线程名字,那么线程名字就默认为 Thread-0、 Thread-1、 Thread-2 ......(给线程取名字并不会影响到线程的执行效果,主要是为了便利于我们调试线程的时候,我们自己方便辨认)

(2)Thread 的几个常见属性 

2 . 1 ID 是线程的唯一标识,且它是 JVM 自动分配的,并不能手动修改。

2 . 2 名称是我们使用各种调试工具时,便于我们辨别的。

2 . 3 状态表示当前线程所处的一个情况,例如 Runnable 表示 “ 就绪状态(同时也表示我们的运行状态)”,关于状态,这里不过多介绍了,后续应该会更详细地讲到。

2 . 4 优先级高的线程,理论上来说更容易被调度到。

2 . 5 这里提到了后台线程,还有一个伴生的概念叫做前台线程,对于这两个概念,我会在下期做出详细的解释

2 . 6 是否存活这应该很好理解,就是用来判断我们的 run 方法是否运行结束了。

OKK,这次就先说到这里吧,大家有什么不理解的,又或是我在文中有什么错误,都欢迎诸君跟我聊聊,大家加油,与诸君共勉!!!

http://www.xdnf.cn/news/415513.html

相关文章:

  • 2025/5/7 心得
  • 进销存ERP系统,Java+Vue,含源码及文档,整合进销存各环节,实现数据精准互通,提升企业运营效能
  • 1.1 文章简介
  • Linux——数据库备份与恢复
  • C++哈希表
  • Fellou智能体调研
  • Python训练营打卡DAY23
  • c++ 类的成员初始化
  • [Windows] PicPick Professional_v7.3.4 中文专业版
  • SpringDataRedis的入门案例,以及RedisTemplate序列化实现
  • 18.three官方示例+编辑器+AI快速学习webgl_buffergeometry_points_interleaved
  • Ascend的aclgraph(五)PrimTorch TorchInductor
  • USB学习【10】描述符-HID描述符
  • Stream Deck纯软件实现高性价比平替
  • 多线程(2)——Thread类及常见方法
  • 2025年上半年软考备考攻略:关键事项提醒
  • Java知识库网站整理
  • CHIP第四次作业
  • [编程基础] PHP · 学习手册
  • Spring事务中异步操作导致数据查询失败问题分析与解决方案
  • SHA-256 哈希算法详解
  • DNS工作原理与报文解析
  • Docker快速入门与应用
  • 基于Arduino的贪吃蛇游戏机
  • 位运算题目:黑板异或游戏
  • 火山云网站搭建
  • AES-128 加密与解密详解
  • 分享AI时代数据智能人才定向就业班(暑期班)
  • 【Linux 系统调试】syslog:Linux 系统日志工具详解
  • DAY22kaggle泰坦尼克号