JobSchedulerç使ç¨ååç
JobScheduler主è¦ç¨äºå¨æªæ¥æ个æ¶é´ä¸æ»¡è¶³ä¸å®æ¡ä»¶æ¶è§¦åæ§è¡æ项任å¡çæ åµï¼æ¶åçæ¡ä»¶å¯ä»¥æ¯ç½ç»ãçµéãæ¶é´çï¼ä¾å¦æ§è¡ç¹å®çç½ç»ãæ¯å¦åªå¨å çµæ¶æ§è¡ä»»å¡çãJobSchedulerç±»è´è´£å°åºç¨éè¦æ§è¡çä»»å¡åéç»æ¡æ¶ï¼ä»¥å¤å¯¹è¯¥åºç¨Jobçè°åº¦ï¼æ¯ä¸ä¸ªç³»ç»æå¡ï¼å¯ä»¥éè¿å¦ä¸æ¹å¼è·åï¼
JobInfoæ¯ä¼ éç»JobSchedulerç±»çæ°æ®å®¹å¨ï¼å®å°è£ äºé对è°ç¨åºç¨ç¨åºè°åº¦ä»»å¡æéçåç§çº¦æï¼ä¹å¯ä»¥è®¤ä¸ºä¸ä¸ªJobInfo对象对åºä¸ä¸ªä»»å¡ï¼JobInfo对象éè¿JobInfo.Builderå建ãå®å°ä½ä¸ºåæ°ä¼ éç»JobSchedulerï¼
JobInfo.Builderæ¯JobInfoçä¸ä¸ªå é¨ç±»ï¼ç¨æ¥å建JobInfoçBuilderç±»ã
JobServiceæ¯JobScheduleræç»åè°ç端ç¹ï¼JobSchedulerå°ä¼åè°è¯¥ç±»ä¸çonStartJob()å¼å§æ§è¡å¼æ¥ä»»å¡ãå®æ¯ä¸ä¸ªç»§æ¿äºJobServiceçæ½è±¡ç±»ï¼å为系ç»åè°æ§è¡ä»»å¡å 容çç»ç«¯ï¼JobScheduleræ¡æ¶å°éè¿bindService()æ¹å¼æ¥å¯å¨è¯¥æå¡ãå æ¤ï¼ç¨æ·å¿ é¡»å¨åºç¨ç¨åºä¸å建ä¸ä¸ªJobServiceçåç±»ï¼å¹¶å®ç°å ¶onStartJob()çåè°æ¹æ³ï¼ä»¥åå¨AndroidManifest.xmlä¸å¯¹å®æäºå¦ä¸æéï¼
注æå¨AndroidManifest.xmlä¸æ·»å æé
å½ä»»å¡å¼å§æ¶ä¼æ§è¡onStartJob(JobParameters params)æ¹æ³ï¼å¦æè¿åå¼æ¯falseï¼åç³»ç»è®¤ä¸ºè¿ä¸ªæ¹æ³è¿åæ¶ï¼ä»»å¡å·²ç»æ§è¡å®æ¯ãå¦æè¿åå¼æ¯trueï¼é£ä¹ç³»ç»è®¤ä¸ºè¿ä¸ªä»»å¡æ£è¦è¢«æ§è¡ï¼æ§è¡ä»»å¡çéæ å°±è½å¨äºä½ çè©ä¸ãå½ä»»å¡æ§è¡å®æ¯æ¶ä½ éè¦è°ç¨jobFinished(JobParameters params, boolean needsRescheduled)æ¥éç¥ç³»ç»ã
å½ç³»ç»æ¥æ¶å°ä¸ä¸ªåæ¶è¯·æ±æ¶ï¼ç³»ç»ä¼è°ç¨onStopJob(JobParameters params)æ¹æ³åæ¶æ£å¨çå¾ æ§è¡çä»»å¡ãå¾éè¦çä¸ç¹æ¯å¦æonStartJob(JobParameters params)è¿åfalseï¼é£ä¹ç³»ç»åå®å¨æ¥æ¶å°ä¸ä¸ªåæ¶è¯·æ±æ¶å·²ç»æ²¡ææ£å¨è¿è¡çä»»å¡ãæ¢å¥è¯è¯´ï¼onStopJob(JobParameters params)å¨è¿ç§æ åµä¸ä¸ä¼è¢«è°ç¨ã
éè¦æ³¨æçæ¯è¿ä¸ªJob Serviceè¿è¡å¨ä¸»çº¿ç¨ï¼è¿æå³çä½ éè¦ä½¿ç¨å线ç¨ï¼handlerï¼æè ä¸ä¸ªå¼æ¥ä»»å¡æ¥è¿è¡èæ¶çæä½ä»¥é²æ¢é»å¡ä¸»çº¿ç¨ã
Googleå®æ¹çSampleï¼ /googlearchive/android-JobScheduler
JobScheduleræ¯ä¸ä¸ªæ½è±¡ç±»ï¼å®å¨ç³»ç»æ¡æ¶çå®ç°ç±»æ¯android.app.JobSchedulerImpl
æ§è¡çå ¥å£æ¯JobScheduler.schedulerï¼å ¶å®æ¯è°äºJobSchedulerImplä¸çscheduleæ¹æ³ï¼ç¶ååè°äºmBinder.schedule(job)ãè¿ä¸ªmBinderå°±æ¯JobSchedulerServiceï¼éè¿Binderè·¨è¿ç¨è°ç¨JobSchedulerServiceã
æåè°ç¨å°JobSchedulerServiceä¸çscheduleæ¹æ³:
æ¥çåéMSG_CHECK_JOBæ¶æ¯ï¼æ¶æ¯å¤ççå°æ¹æ¯
æ¥çæ§è¡JobHandlerä¸ç maybeRunPendingJobsH æ¹æ³ï¼å¤çç¸åºçä»»å¡
availableContextæ¯JobServiceContextï¼å³ServiceConnectionï¼è¿ä¸ªæ¯è¿ç¨é´é讯ServiceConnectionï¼éè¿è°ç¨availableContext.executeRunnableJob(nextPending)æ¹æ³ï¼ä¼è§¦åè°ç¨onServiceConnectedï¼çå°è¿éåºè¯¥æç½äºï¼onServiceConnectedæ¹æ³ä¸çserviceå°±æ¯Jobserviceï¼éé¢è¿ç¨äºWakeLockéï¼é²æ¢ææºä¼ç ã
æ¥çï¼éè¿Handleråæ¶æ¯ï¼è°ç¨äºhandleServiceBoundH()æ¹æ³ã
ä»ä¸é¢æºç å¯ä»¥çåºï¼æç»æ¯è§¦åè°ç¨äºJobServiceä¸çstartJobæ¹æ³ã
ä»æºç çï¼è®¾ç½®çå 容åºç¨äº JobStatus ï¼ä¾å¦ç½ç»éå¶
èå¨JobSchedulerServiceç±»ï¼ç¸å ³çç¶ææ§å¶å¨å ¶æé å½æ°é:
ä¾å¦ç½ç»æ§å¶ç±»ConnectivityControllerç±»
å½ç½ç»åçæ¹åæ¶ï¼ä¼è°ç¨updateTrackedJobs(userid)æ¹æ³ï¼å¨updateTrackedJobsæ¹æ³ä¸ï¼ä¼å¤æç½ç»æ¯å¦ææ¹åï¼ææ¹åçä¼è°mStateChangedListener.onControllerStateChanged()æ¹æ³ï¼ç¶åè°ç¨äºJobSchedulerServiceç±»ä¸onControllerStateChangedæ¹æ³ï¼
æ¥çä¹æ¯å¤çMSG_CHECK_JOB æ¶æ¯ï¼åä¸æä¸æ ·ï¼æç»è§¦åè°ç¨äºJobServiceä¸çstartJobæ¹æ³ã
JobSchedulerServiceæ¯ä¸ä¸ªç³»ç»æå¡ï¼å³åºè¯¥å¨SystemServerå¯å¨çãé 读SystemServerçæºç ï¼
run æ¹æ³å¦ä¸ï¼
æ¥çç startOtherServices()
å æ¤ï¼å¨è¿éå°±å¯å¨äºJobSchedulerServiceæå¡ã
1. android æ§è½ä¼åJobScheduler使ç¨åæºç åæ
2. Android 9.0 JobScheduler(ä¸) JobSchedulerç使ç¨
3. Android 9.0 JobScheduler(äº) JobScheduleræ¡æ¶ç»æç®è¿°åJobSchedulerServiceçå¯å¨
4. Android 9.0 JobScheduler(ä¸) ä»Jobçå建å°æ§è¡
5. Android 9.0 JobScheduler(å) Job约ææ¡ä»¶çæ§å¶
6. ç解JobScheduleræºå¶
深入理解 RxJava2:Scheduler(2)
欢迎来到深入理解 RxJava2 系列第二篇,本文基于 RxJava 2.2.0 正式版源码,程源池将探讨 Scheduler 与 Worker 的线线程概念及其实现原理。
Scheduler 与 Worker 在 RxJava2 中扮演着至关重要的程源池角色,它们是线线程线程调度的核心与基石。虽然 Scheduler 的程源池源码则么作用较为熟悉,但 Worker 的线线程概念了解的人可能较少。为何在已有 Scheduler 的程源池情况下,还要引入 Worker 的线线程概念呢?让我们继续探讨。
首先,程源池Scheduler 的线线程核心定义是调度 Runnable,支持立即、程源池延时和周期性调用。线线程而 Worker 是程源池任务的最小单元的载体。在 RxJava2 内部实现中,线线程通常一个或多个 Worker 对应一个 ScheduledThreadPoolExecutor 对象,这里暂不深入探讨。
在 RxJava 1.x 中,Scheduler 没有 scheduleDirect/schedulePeriodicallyDirect 方法,只能先创建 Worker,再通过 Worker 来调度任务。这些方法是对 Worker 调度的简化,可以理解为创建一个只能调度一次任务的 Worker 并立即调度该任务。在 Scheduler 基类的源码中,默认实现是直接创建 Worker 并创建对应的 Task(虽然在部分 Scheduler 的覆盖实现上并没有创建 Worker,但可以认为存在虚拟的 Worker)。
一个 Scheduler 可以创建多个 Worker,这两者是一对多的关系,而 Worker 与 Task 也是一对多的关系。Worker 的存在旨在确保两件事:统一调度 Runnable 和统一取消任务。例如,在 observeOn 操作符中,可以通过 Worker 来统一调度和取消一系列的 Runnable。
RxJava2 默认内置了多种 Scheduler 实现,适用于不同场景,这些 Scheduler 都可以在 Schedulers 类中直接获得。以下是两个常用 Scheduler 的源码分析:computation 和 io。
NewThreadWorker 在 computation、io 和 newThread 中都有涉及,下面简单了解一下这个类。NewThreadWorker 与 ScheduledThreadPoolExecutor 之间是一对一的关系,在构造函数中通过工厂方法创建一个 corePoolSize 为 1 的买票APP源码 ScheduledThreadPoolExecutor 对象并持有。
ScheduledThreadPoolExecutor 从 JDK1.5 开始存在,这个类继承于 ThreadPoolExecutor,支持立即、延时和周期性任务。但是注意,在 ScheduledThreadPoolExecutor 中,maximumPoolSize 参数是无效的,corePoolSize 表示最大线程数,且它的队列是无界的。这里不再深入探讨该类,否则会涉及太多内容。
有了这个类,RxJava2 在实现 Worker 时就站在了巨人的肩膀上,线程调度可以直接使用该类解决,唯一的麻烦之处就是封装一层 Disposable 的逻辑。
ComputationScheduler 是计算密集型的 Scheduler,其线程数与 CPU 核心数密切相关。当线程数远超过 CPU 核心数目时,CPU 的时间更多地损耗在了线程的上下文切换。因此,保持最大线程数与 CPU 核心数一致是比较通用的方式。
FixedSchedulerPool 可以看作是固定数量的真正 Worker 的缓存池。确定了 MAX_THREADS 后,在 ComputationScheduler 的构造函数中会创建 FixedSchedulerPool 对象,FixedSchedulerPool 内部会直接创建一个长度为 MAX_THREADS 的 PoolWorker 数组。PoolWorker 继承自 NewThreadWorker,但没有任何额外的代码。
PoolWorker 的使用方法是从池子里取一个 PoolWorker 并返回。但是需要注意,每个 Worker 是独立的,每个 Worker 内部的任务是绑定在这个 Worker 中的。如果按照上述方法暴露 PoolWorker,会出现两个问题:
为了解决上述问题,需要在 PoolWorker 外再包一层 EventLoopWorker。EventLoopWorker 是一个代理对象,它会将 Runnable 代理给 FixedSchedulerPool 中取到的 PoolWorker 来调度,并负责管理通过它创建的任务。当自身被取消时,会将创建的任务全部取消。
与 ComputationScheduler 恰恰相反,IoScheduler 的ntp源码分析线程数是无上限的。这是因为 IO 设备的速度远低于 CPU 速度,在等待 IO 操作时,CPU 往往是闲置的。因此,应该创建更多的线程让 CPU 尽可能地利用。当然,并不是线程越多越好,线程数目膨胀到一定程度会影响 CPU 的效率,也会消耗大量的内存。在 IoScheduler 中,每个 Worker 在空置一段时间后就会被清除以控制线程的数目。
CachedWorkerPool 是一个变长并定期清理的 ThreadWorker 的缓存池,内部通过一个 ConcurrentLinkedQueue 维护。和 PoolWorker 类似,ThreadWorker 也是继承自 NewThreadWorker。仅仅是增加了一个 expirationTime 字段,用来标识这个 ThreadWorker 的超时时间。
在 CachedWorkerPool 初始化时,会传入 Worker 的超时时间,目前是写死的 秒。这个超时时间表示 ThreadWorker 闲置后最大存活时间(实际中不保证 秒时被回收)。
IoScheduler 中也存在一个 EventLoopWorker 类,它和 ComputationScheduler 中的作用类似。因为 CachedWorkerPool 是每隔 秒清理一次队列的,所以 ThreadWorker 的存活时间取决于入队的时机。如果一直没有被再次取出,其被实际清理的延迟在 - 秒之间。
熟悉线程的读者会发现,ComputationScheduler 与 IoScheduler 很像某些参数下的 ThreadPoolExecutor。它们对线程的控制外在表现很相似,但实际的线程执行对象不一样。这两者的对比有助于我们更深刻地理解 Scheduler 设计的内在逻辑。
Scheduler 是 RxJava 线程的核心概念,RxJava 基于此屏蔽了 Thread 相关的概念,只与 Scheduler/Worker/Runnable 打交道。
本来计划继续基于 Scheduler 和大家一起探讨 subscribeOn 与 observeOn,但考虑到篇幅问题,这些留待下篇分享。
感谢大家的阅读,欢迎关注笔者的公众号,可以第一时间获取更新,加菲猫pc源码同时欢迎留言沟通。
ThreadPoolTaskScheduler 在 Main 函数和 Spring 环境下的使用
在非Spring环境的main函数中优雅使用ThreadPoolTaskScheduler
在Java开发中,ThreadPoolTaskScheduler用于处理定时任务,尤其在非Spring环境下。然而,直接使用ThreadPoolTaskScheduler可能会导致java.lang.IllegalStateException: ThreadPoolTaskScheduler not initialized错误。为解决此问题,需在调度任务前手动初始化ThreadPoolTaskScheduler。
步骤如下:
1. 调用taskScheduler.initialize()方法初始化ThreadPoolTaskScheduler,避免异常。
在Spring环境下使用ThreadPoolTaskScheduler更为简便。通过配置类,可轻松实现其使用。具体步骤为:
1. 创建线程池配置。
2. 在使用处注入线程池并调度任务。
Spring框架提供的ThreadPoolTaskScheduler,无论是非Spring环境的main函数中,还是Spring环境下的配置与使用,均需关注初始化步骤,确保ThreadPoolTaskScheduler正确运行,高效处理定时任务。
spring 定时任务Scheduler和异步任务Async
Spring框架通过TaskExecutor和TaskScheduler接口提供异步任务执行和任务调度功能。
对于定时任务Scheduler,Spring Boot默认使用ScheduledThreadPoolExecutor,核心线程数为1。要实现定时任务,只需在启动类上添加@EnableScheduling注解,并在需要执行的任务方法上使用@Scheduled。例如,一个每秒执行一次的任务,尽管配置为每秒运行,但实际执行会等待前一次任务完成后。Spring提供了配置项,如TaskSchedulingProperties,用于调整线程池设置。
异步任务Async使用Async和@EnableAsync注解,Spring Boot默认Async线程池核心大小为8。在方法上使用@Async,任务将并发执行。配置选项可通过TaskExecutionProperties查看,如线程池大小。2020搜索源码若需自定义线程池,可创建TaskExecutor bean并指定在@Async中使用。
在调度频率上,@Scheduled支持cron表达式和固定周期。cron表达式提供了强大的任务调度能力,而Async和Scheduler在cron配置下的行为有所不同。Spring还提供了宏来简化常见的cron表达式,如每小时执行一次的表达式。
深入了解这些概念和配置,可以参考Spring官方文档和相关技术博客。
《深入理解react》之调度引擎——Scheduler
深入理解react
在react 版本发布以来的近两年时间里,许多伙伴都体验到了并发模式带来的爽感,createRoot()的使用让应用有了更流畅的体验。而这一切的核心,便是react执行流中的调度引擎——Scheduler。调度,这个概念在计算机行业中广泛存在,无论是操作系统、浏览器还是大型应用,都离不开调度任务的需求。Scheduler,作为独立的包,不仅可以在react中使用,更可以在任何其他库中发挥作用,其简洁的源码使深入理解react成为可能。
为何需要调度器?首先是为了解决卡顿问题。在js引擎和渲染绘制都在同一线程执行的情况下,如何保证帧的刷新频率不被CPU密集型任务阻塞?其次,react会生成具有优先级的任务,优先级高的任务可能在后面产生,调度器能确保优先级高的任务优先执行,以提升用户体验。
Scheduler通过暴露的方法如unstable_scheduleCallback,可以按照优先级的高低顺序调度任务,并保证异步执行。在实际体验中,我们可以创建工程来测试Scheduler的执行时机,发现它会遵循优先级顺序,优先执行高优先级任务,并在下一个宏任务中异步执行。
源码解析中,小根堆作为关键数据结构,用于维护优先级队列。Scheduler使用小根堆来管理任务,优先级最高的任务始终处于堆顶。优先级的动态调整确保了任务在调度过程中的灵活排序。例如,随着时间推移,新任务的优先级会逐渐提高,使得原有任务在下一个周期中优先执行。
Scheduler的核心逻辑在工作循环中体现,通过合理调度不同优先级的任务,既不阻碍UI绘制,又能高效执行任务。对于大任务,用户可以通过拆分策略,将其划分为多个小任务,以避免阻塞UI,实现流畅的用户体验。
最后,Scheduler在react中扮演着关键角色,通过合理的任务调度,确保应用流畅运行。深入理解Scheduler,将为深入理解react提供坚实的基础。关注专栏,获取更多react相关知识。
如何利用python实现定时程序?
在日常工作中,利用Python实现定时任务,主要可通过多种方法实现,包括使用循环与sleep()函数、Timeloop库、threading.Timer、内置模块sched、schedule第三方库、以及调度模块APScheduler等。下面分别介绍这些方法及其特点。
利用while True: + sleep()实现定时任务,通过循环和sleep()函数,可实现简单定时任务。示例代码如下:
基于time模块的sleep(secs)函数,可使线程暂停secs秒后再执行。这使得我们可以通过循环调用sleep()函数来实现定时任务。
缺点:循环调用可能导致任务执行效率不高。
利用Timeloop库实现定时任务,这个库使用decorator模式运行标记函数。示例代码如下:
利用threading.Timer实现定时任务,它是一个非阻塞函数,支持启动多个异步执行的定时任务。
Timer(interval, function, args=[ ], kwargs={ })
缺点:仅能执行一次任务,需要循环调用。
利用内置模块sched实现定时任务,sched模块提供通用事件调度器,支持多线程,确保任务在执行后立即进行延时,以确保其他线程也能执行。
class sched.scheduler(timefunc, delayfunc)
缺点:需要外部传入timefunc和delayfunc。
利用schedule第三方库实现定时任务,支持按秒、分、小时、日期或自定义事件执行时间。schedule提供简单、易懂的语法,定期运行Python函数。
装饰器:@repeat()装饰静态方法
传递参数:可传递参数至装饰器
取消任务:支持取消任务
运行一次任务:实现一次性任务执行
根据标签检索和取消任务:支持按标签管理任务
运行任务至指定时间:控制任务执行时间
并行运行:利用Python内置队列实现多任务并行执行
利用APScheduler实现定时任务,这是一个基于Quartz的Python定时任务框架,支持日期、固定间隔和crontab类型任务,且可持久化任务。其特点包括四个组成部分:Job、Trigger、Executor和Jobstore,以及重要概念如Job、Trigger、Executor、Jobstore、Event和Scheduler。
Job作为最小执行单元,包含执行函数、参数和执行设置信息。
Trigger绑定到Job,计算执行时间,与当前时间比较确定执行时间。
支持的Trigger参数包括:date(定时执行)、interval(间隔调度)和cron(定时任务)。
Executor用于执行Job,支持不同调度方式。
Jobstore用于存储任务,支持内存存储、数据库存储等。
Event表示Scheduler触发的事件,用户可自定义处理函数。
Scheduler是核心组件,负责任务调度。
利用Celery实现定时任务,这是一个分布式系统,支持大量消息处理和任务调度。Celery配置相对复杂,适用于大规模任务处理,支持异步任务和定时任务,但不自带任务存储功能,需要配合消息队列、Redis缓存或数据库等存储。
使用Apache Airflow实现定时任务,这是一款数据流程工具,以灵活的方式支持数据ETL过程,支持插件扩展,如HDFS监控、邮件通知等,适合单机或分布式模式运行。
Apache Airflow的核心概念是DAG,表示工作流中任务执行顺序和依赖关系。它提供多种Operator实现各种任务需求,并支持分支执行逻辑,如根据执行结果执行不同任务。
总结,Python提供多种方法实现定时任务,从基础的循环与sleep()函数到高级的APScheduler和Celery等库,开发者可以根据具体需求选择合适的方法,实现高效、灵活的定时任务管理。
.8 XV6线程切换 --- scheduler函数
深入探讨scheduler函数的作用和工作原理。在当前运行的调度器线程中,我们执行switch函数以运行PID为3的进程,该进程是通过中断机制被唤醒的。值得注意的是,虽然PID为3的进程也调用了switch函数,但这里讨论的switch函数与spin进程调用的那一个不同。spin进程调用的switch函数还未返回,其相关信息保存在spin进程的栈和context对象中。当前执行的switch函数是调度器线程之前调用的那一个。
执行scheduler函数时,需要抹去spin进程的记录,通过将c->proc设置为0来完成。此举是为了避免混淆,表示当前CPU核上没有运行进程。释放spin进程的锁是必要的,因为yield函数希望在进程完全进入Sleep状态前,不让其他CPU核的调度器线程访问并运行此进程。切换完成后,释放锁,允许其他CPU核发现并运行spin进程,因为spin进程现在是RUNABLE状态。尽管我们当前CPU核上运行的是调度器线程,但其他CPU核仍然可以运行spin进程,因为spin进程的状态已被完整保存,且不在当前CPU核的调度器线程栈上运行程序。
在scheduler函数中,p->lock的使用有两层意义。首先,它确保了三个关键步骤的原子性:将进程状态从RUNNING更改为RUNABLE,保存进程寄存器在context对象中,并停止使用当前进程的栈。这样,其他CPU核的调度器线程无法在这些步骤完成之前看到当前进程。其次,当准备启动一个进程时,p->lock同样保护了进程状态的改变,以防止在寄存器完全恢复之前被中断,从而避免了在切换过程中保存不完整RISC-V寄存器到进程context对象的问题。
在scheduler函数循环中,找到一个可运行的进程并开始执行。通过跳过进程检查并直接设置断点,我们可以观察执行流程。在代码的行获取进程锁后,执行切换到进程的各种步骤。进程状态在行设置为RUNNING,并在行记录为当前CPU执行的进程。通过行调用switch函数,调度器线程的寄存器被保存,目标进程的寄存器被恢复。打印新进程名字,确认切换成功。
通过查看目标进程的context对象,我们可以观察到ra寄存器指向切换到的目标线程的代码位置。尽管在行调用了switch函数,关键在于ra指向的位置,即switch函数返回后继续执行的地址。这将返回到调度器线程中的sched函数。实际的进程切换在switch函数内部完成,返回到目标进程的内核线程的sched函数,通过打印backtrace,可以看到yield和sched函数的调用。这一过程与之前观察到的pid为3的进程不同,现在涉及的是pid为4的进程。
学生提问关于非定时器中断触发的进程切换时,ra寄存器指向的位置。教授解释,确实存在系统调用相关的函数,例如sleep,其也会调用sched函数。即使在不同上下文下,切换过程的核心是通过switch函数实现的,该函数负责保存和恢复处理器中的寄存器。线程除了寄存器外,还包含变量、堆数据等状态,这些数据保存在内存中,不会因切换而改变。因此,线程切换过程中只关注处理器寄存器的保存与恢复,以确保在新线程中使用相同的一组寄存器。
2024-11-30 15:21
2024-11-30 15:10
2024-11-30 15:06
2024-11-30 15:00
2024-11-30 13:36