单线程能不能实现并发
乍一看这个问题,我第一时间的想法是并发这个词跟单线程好像并不沾边?在我的刻板印象里好像只有多线程和并发有关
但我回想起我的计算机基础,我很确定的是,单线程指的是只有一个执行线程,在任意时刻只能执行一个任务。
因此在传统意义上,单线程它就是没有办法实现真正的并发的,但是单线程是可以实现类似并发的效果的
我称这种效果为 "伪并发" ,给大家列举一下实现 "伪并发" 的一些方式
-
时间分片:在单线程中在每个单位时间里,通过切换不同任务的执行顺序,模拟多个任务同时执行的效果 通过任务调度器,可以让不同任务交替执行,从而实现 "伪并发"。这里可以联系单核CPU和多核CPU的概念
-
事件循环 :使用事件驱动模型,在单线程中处理多个事件。通过事件循环机制,程序可以同时处理多个事件 看上去是同时发生的,其实是一种 "伪并发"
-
协程:协程可以在单线程中实现并发执行,通过协程的切换机制,程序可以在不同的执行点之间快速切换,实现 "伪并发"
-
异步编程:异步编程是一种编程范式,它允许程序在执行时不会因为等待某个操作(如I/O操作或网络请求)的结果而阻塞主线程的其他任务。这种编程模式使得应用程序能够更加高效地利用系统资源。(这里可能不好理解,可以往下看)
那什么是协程
老实说,第一次接触协程,一脸懵 ,查阅了很多资料也根本不知道这协程到底怎么回事,经过单线程实现 "伪并发" 的理论后
对协程总算是有了一点理解,本文的描述可能不怎么严谨,主要是让大家对协程有一点认识
在我尝试对协程进行理解的时候,我脑子里面就构筑了这个模型,我就在想,那不是有多线程吗?为什么还需要在单线程里面
再搞个协程呢?对于这个问题就想了想多线程有什么问题呢?为什么会需要在单线程里面开协程这个概念呢?
直接给大家上结论:多线程的开销最主要是来源于线程阻塞唤醒调度
相信大家对减少上下文切换 这个概念并不陌生,翻译过来就是减少线程阻塞唤醒的调度次数
好,我们正式进入协程的概念的理解,允许在单个线程内执行多个并发的、非抢占式的控制流。协程的特点和优势在于,它们能够在运行时主动挂起自己的执行,并将控制权返回给调用者或其他协程。当条件满足或被其他协程唤醒时,可以从上次挂起的地方恢复执行。
其实到这里大家可能对为什么要使用协程有了一点苗头了,大胆发文,协程可以减少线程阻塞唤醒调度的开销,切换成本低
就是这样,那么为什么协程与传统线程相比,切换成本更低了?
因为协程的上下文切换完全在用户空间进行,不需要像操作系统调度线程那样涉及内核态的切换。此外,协程的调度策略由程序员自行控制,因此可以更灵活地管理资源并实现协同式多任务处理。
什么是异步编程
异步编程是一种处理非阻塞IO和并发任务的编程方式,简单来说就是开启另一个服务或者线程去处理任务
-
使用线程和Runnable/Callable接口:Java中最基本的异步编程方式是通过创建线程来实现。可以通过实现Runnable接口或Callable接口 ,并将其传递给Thread类来创建线程。这样可以在单独的线程中执行任务,从而实现异步操作。
-
使用Future和Callable:Java中的Futrue接口和Callable接口可以用于异步执行任务并获取任务的结果。Callable接口类似于Runnable接口,但可以返回任务的执行接口。Future接口可以用来获取异步执行任务的执行状态和结果。
-
使用FutureTask(不推荐)或CompleableFuture(推荐):Java8引入了CompleableFuture类,它提供了更强大和更灵活的异步编程功能。Compleable可以用于组合多个异步任务,处理任务的结果和异常,以及实现复杂的异步操作流程。
-
引用消息队列:可以通过生产消息发送到消息队列,通过消息队列进行解耦,实现业务逻辑的异步操作
123点这样开启额外的线程去处理,还是多线程那个意思,这里只是举个异步编程的例子,消息队列这就没有用到多线程了
什么是事件循环
相信学过JavaScript和Node的人对事件循环那肯定是熟悉的很
Event Loop 即事件循环, 是JavaScript或Node为解决单线程代码执行不阻塞主进程一种机制,也就是我们所说的异步原理。
事件循环负责执行代码、收集和处理事件以及执行队列中的子任务。
-
整个运行机制是这样的
-
整体的script(作为第一个宏任务)开始执行的时候,会把所有代码分为两部分:"同步任务"、"异步任务"
-
同步任务会直接进入主线程依次执行
-
异步任务 会再分为宏任务 (进入宏任务队列) 和 微任务(进入微任务队列)
-
当主线程内的任务执行完毕 (主线程为空时),会检查微任务的任务队列,如果有任务,就进入主线程全部执行,如果没有就从宏任务队列读取下一个宏任务执行
-
每执行完一个宏任务就清空一次微任务队列,此过程会不断重复,这就是Event Loop
-