多线程概述
文章目录
- 线程是什么
- 线程有什么作用
- 线程和进程的区别
- 多线程相较于进程优势
在Java这个圈子中,多进程用的并不多,因为进程是一个重量级操作,进程是资源分配的基本单位,申请资源是一个比较消耗时间的操作.
线程是什么
- 线程是一个独立的执行流,可以被独立调度到CPU上执行
- 线程是操作系统调度执行的基本单位
- 每个线程之间都可以按照顺讯执行自己的代码.
- 多个线程之间并发执行着多份代码.
举个例子,市面上有很多多线程下载器,如IDM,NDM等.这些多线程下载器在下载文件时,就可以把一个任务分为多个子任务,然后让每个线程完成一个子任务,每一个线程都是一个独立的执行流.这样做就可以增加下载速度.
我们补充一点,线程是系统调度执行的最小单位,在线程执行过程中,操作系统中就不会再有进程这样的概念了,每个线程可以独立的进行调度。而线程也一样拥有PCB(Process Control Blob),只不过其中的进程标识符pid,内存指针,和文件描述符表是共用的,因为线程共享进程的资源。但是线程的PCB中状态、优先级、上下文、记账信息等影响调度执行的属性私有的(各不相同)。
线程有什么作用
单核心CPU发展遇到瓶颈,通过增加CPU核心,提高算力,而并发编程就能够充分利用CPU的多个核心,从而将CPU的性能发挥到极致。在有些IO场景下,CPU就会有“闲置”,并发就能充分利用这部分空闲的CPU资源。总之,线程是用来实现高并发场景的,而高并发能提高程序执行的效率。
那么进程也能实现高并发场景,我们在Java中为什么不推荐使用多进程编程,而推荐使用多线程编程呢?那是因为虽然多进程也能实现 并发编程, 但是线程比进程更轻量。进程是操作系统资源分配的最小单位,而多进程编程,会频繁的创建、销毁、调度进程,而这其中最大的时间消耗其实是申请资源,分配内存/硬盘是一个重量级的操作。
主要是由于操作系统要管理大量的空闲的内存和硬盘资源。虽然操作系统中使用了一定的数据结构,把这些空间管理的还不错,但是即使如此,申请资源仍然还是一个低效操作。如果只申请一次资源,开销也就还不错,但如果频繁的申请和释放资源,开销就不可忽视了。
线程也叫作轻量级进程
- 创建线程比创建进程更快
- 销毁线程比销毁进程更快
- 调度线程比调度进程更快
虽然线程比进程更加轻量化,但是为了更加轻量(开销小,效率高)于是又引入了线程池(ThreadPool) 和 “协程”(Coroutine)这样的概念来进一步提高效率,我们后面会介绍到。
线程和进程的区别
- 本质区别在于,每个进程都拥有自己的一整套资源,而线程则是共享资源,开销小,更加轻量化
- 内存指针和文件描述符表维护的进程创建时申请的内存和硬盘资源
- 进程包含线程,一个进程至少有一个线程即主线程。
- 进程是系统资源分配的最小单位,而线程则是系统调度的最小单位
- 进程之间具有独立性,一个进程崩溃,不会影响其他进程,而线程之间共享资源,一个线程崩溃可能会影响到其他的线程,严重的还可能会让线程所在的进程崩溃
多线程相较于进程优势
多线程在一些场景下是可以大大提高运行效率的。如果现在要下载一个100G大小的文件,我们可以怎么做呢?
方案一:将下载任务分成多个子任务,交给多个下载器下载.(多进程方式)
这种方式虽然可以提高下载速度,但是开启多个下载器,在操作系统中创建了多个进程,申请了更多的资源,开销比较大.
方案二: 在一个下载器中开启多线程下载(多线程)
相较于多进程的方式,这种多线程的方式,复用了进程申请的资源,降低了申请资源上的开销,是一种更加轻量化的方案
补充一点,刚开始创建进程时,主线程会随着进程一起被创建出来,这个时候也是有着一定的申请资源的开销的,但是这个开销并不会算在线程头上,而是记在了进程头上,而后面如果继续创建线程,则会复用进程的资源,开销也自然就小了。