多线程机制 (一)

多线程机制涉及到底层CPU处理机制,在学习的过程中不仅可以对CPU、内存等等都进一步的深入理解。这也是我(计算机小白)最喜欢的,知识是融会贯通的,相信很多人听过无数次,个人现在感觉学习知识,不应该是按部就班的学习,当学习时碰到了新名词就立即去学,一方面可以加深记忆,但是也有坏处,就像我学习多线程机制,是因为我在学算法,算法中遇到了异常处理中的无限递归问题,所以我又去了解,后来又发现和线程有关,所以我准备了解一下线程。但是学习是活的,只要你发现问题,就一定有自己的方法取解决。

一般的应用程序都是单线程的程序,也就是说,一个程序,从头到尾都是按顺序执行语句的, 在程序开始至结束的这一段时间只做一件事情,从而使高效的 CPU 很多时间都被闲置, 为了更好的利用CPU的资源, Java语言提供了多线程机制,可以再设计一个程序的时候考虑在一段时间内同时做多件事情。

主要解决问题:

  • 什么是进程? 什么是多线程?
  • 多线程与多任务有什么区别?
  • 什么是Java的多线程机制?
  • 如何编写多线程的程序?
  • 为什么要建立线程的同步机制?
  • 什么是同步方法? 什么是同步对象?
  • 多线程程序有哪些需要注意的问题?

如果学习之后能够对这些问题有清晰的回答思路,那么多线程机制就刚刚入门了。

1. 多线程的概念

1.1 程序、进程 和 多任务

  1. 程序
    程序(program) ,是数据描述与操作代码的集合,是应用程序执行的脚本。

  2. 进程
    进程(process)是程序的一次执行过程, 是操作系统运行程序的基本单位, 程序是静态的,进程是动态的。 系统运行一个程序是一个进程从创建、运行到消亡的过程。

操作系统可以为一个程序同时创建多个进程。
打开你的任务管理器,你就可以看见多个进程的存在。操作系统为每一个进程分配有自己独立的一块内存空间和一组系统资源,即使同类进程之间也不会共享系统资源。

  1. 多任务
    多任务是指一个系统中可以同时运行多个程序, 即有多个独立运行的任务,每一个任务对应一个进程, 例如一边使用博客总结书上的知识,一边听计算机播放音乐。 (好像暴露了什么)

由于一个CPU在同一时刻只能执行一个程序中的一条指令,实际上, 多任务运行的并发机制是这些任务交替运行,因间隔时间短,所以我们感觉多个程序在同时运行,如果是多个CPU,可以同时执行多个任务。

1.2 线程

运行一个程序时,程序内部的代码都是按顺序先后执行的。如果能够将一个进程划分为更小的运行单位,则程序中一些彼此相对独立的代码段可以重叠运行, 将会获得更高的执行效率,合情合理,谁不喜欢更快呢?

线程就是来解决这个问题的, 线程是比进程更小的运行单位,一个进程可以由多个线程组成。线程是程序中单个顺序的流控制。

线程是一种特殊的多任务方式。 当一个程序执行多线程时,可以运行两个或更多由同一个程序启动的任务, 这样,当一个程序可以使得多个活动任务同时发生,例如 我们在浏览器中可以一边听音乐,一边浏览网页,一边下载东西。

线程与任何一个程序一样,都有一个开始,一系列可执行的命令序列,一个结束。在执行的任何时刻, 只有一个执行点。线程与程序不同的是线程本身不能运行,它只能包含在程序中,只能在程序中执行,一个线程在程序运行时,就必须争取到为自己分配的系统资源,如执行栈堆,程序计数器。

讲到这里虽然对线程、程序、进程有了一定的认识,但是一知半解是没有意义的。
拓展知识——文章参考:https://zhuanlan.zhihu.com/p/82123111————————————————————

计算机的CPU物理核数是同时可以并行的线程数量, CPU只关心线程,线程是CPU调度分配的最小单位,由于超线程技术,实际上可以并行的线程数通常是物理核数的两倍,即操作系统能看到的核数,以下的核数默认操作系统看到的核数。

进程是操作系统资源分配(内存、显卡、磁盘)的最小单位,须与CPU调度分配的最小单位线程两个定义开来, 对于日常执行资源分配任务的内存、显卡、磁盘来说,它们只关心进程。 而对于日常执行调度分配的CPU来说,它关心的是线程。

在游戏里,一个线程就像是一个任务, 而进程就像是子任务一样,(仅作为辅助理解,不能映射全部)比如说我们玩游戏的时候都会开启一个任务,比如说:

任务:从恶魔洞穴带回国王的女儿

  • 任务 1 : 杀死恶魔洞穴 boss
  • 任务 2 : 收集齐洞穴晶石 0/24
  • 任务 3 :血量不小于1/3。

资源分配(内存、显卡、磁盘)就像是游戏系统一样,它根本不管你到底是先完成任务 1 了还是最后完成任务 1 ,它只要当你3 个任务都完成之后才会显示任务:从恶魔洞穴带回国王的女儿 (即进程)顺利完成。接着有下一个任务交给你,你就是 CPU, 你看的不是 任务:从恶魔洞穴带回国王的女儿,而是, 任务1 、任务2、任务3这些更小的单位、即线程。

为什么要这样做呢? 一个进程可以有多个线程,线程之间共享进程的资源,通过这样的范式,就可以减少进程的创建和销毁带来的代价,可以让进程少一点,保持相对稳定,不断地去调度线程就好。

如果计算机由多个CPU核,且计算机中的总的线程数量小于核数,那线程就可以并运行在不同的核中。

比如说刚才游戏的例子,如果你不是一个人,而是一个联盟,那么你就可以让你的朋友 狗蛋帮自己收集洞穴晶石,让另一个朋友铁锤去杀死恶魔洞穴boss,自己待在营地里保证自己血量不低于 1/3,不一会,这个任务就轻易完成了,多核+ 多线程,并且线程数量小于核数,这样的话CPU就会被充分的利用。

如果是单核多线程, 那多线程之间就还不是并行,而是并发了, 即为了均衡负载,CPU调度器会不断的在单核上切换不同的线程执行,这里有时间片的概念,即CPU分配给各个线程的时间,一般是几十毫秒,很短,所以我们觉得好像是多个线程同时进行一样(就像1秒24帧以上图片人眼就觉得图片动了起来,有时感觉还好人类不是什么全能机器一样,迟钝一些会有更多满足😂)。

并发虽然可以让我们看起不同线程之间的任务是并行执行的(注意,并行是真正的同时进行),但是实际上由于增加了线程切换的开销使得代价更大了,如果是多核多线程,且线程数大于核数,其中有些线程会不断地切换,并发执行,但时间是最大的并行数量还是当前这个进程中的核的数量,所以盲目增加线程数不仅不会让你的程序更快,反而会给你的程序增加额外的开销。

————————结束线————————————

3. 多线程

单个线程没有什么特别的意义,真正有用的是具有多线程的程序。

多线程是相对于单线程而言的,指的是在一个程序中可以定义多个线程并同时运行它们, 每个线程执行不同的任务,与进程不同的是,同类多线程共享一块内存空间和一组系统资源,所以,系统的创建多线程花费单价较小,因此,也称线程为轻负荷进程。(多进程稍后讲)。

4. 线程的生命周期与 Java的多线程机制

4.1 线程的生命周期与状态
同进程一样,一个线程也有从创建、运行到消亡的过程,称为线程的生命周期。线程的使用过程有 创建、可运行、在运行、挂起、死亡 5种状态,称为线程生命周期的 5 个阶段。

(1)创建(New)阶段, 在使用 new 操作符创建并初始化线程对象后, 此时线程已经分配到内存空间和所需要的资源。
(2)可运行(Runnable)阶段: 在使用线程对象的 start 方法后,进入线程队列, 排队等待 CPU的使用权,一旦获得 CPU 使用权,就开始独立运行。
(3)在运行(Running)阶段: 获得 CPU使用权后,正在执行线程对象的 run 方法。
(4)挂起( Not Runnable)阶段: 一个正在执行的线程对象,因为某种特殊原因或需要执行输入输出操作时,将让出 CPU 的使用权,线程进入 挂起状态, 挂起状态的线程不能加入 CPU 使用权的等候队列,必须等到挂起原因消除后,才可以去排队。
(5)死亡(Dead)阶段: 线程执行 run 方法最后一句并退出。 当线程被强制死亡,即使用 stop 方法与 destory 方法。

相信理解起来是不会有任何困难的。

4.2 Java的多线程机制

很多计算机编程语言需要利用外部软件包来实现多线程,而Java语言则内在支持多线程。所有的类都是在多线程思想下定义的当程序加载到内存时,启动主线程。要加载其他线程,程序就要使用 Thread 类(专门用来创建和控制线程的类)和 Runnable接口。

java.lang 中的线程类 Thread 封装了所有需要的线程操作控制,有很多方法用来控制一个线程的运行,休眠、挂起或停止。 这就是 Java 的多线程机制。

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值