news 2026/10/15 9:17:52

MediaPlayer 屏幕常亮机制与 WakeLock 调用链

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
MediaPlayer 屏幕常亮机制与 WakeLock 调用链

晚上躺床上看长视频,屏幕突然熄了,你伸手点亮继续看,没过多久又熄了——被这个场景折磨过的人,大概率不是一个合格的多媒体开发。做视频播放器,有一项基础到不能再基础的需求:视频在播,屏幕就不能灭。Android 给 MediaPlayer 这个经典的播放器 API 准备了一个专门的开关:MediaPlayer.setScreenOnWhilePlaying(boolean)。很多新手第一反应是去开PowerManager.WakeLock,或者给布局写死android:keepScreenOn="true",但只要你用的是MediaPlayer + SurfaceView这套组合,系统早就把更匹配的链路封装好了。

这是我在 Android 进阶系列里的第二百五十三篇。这篇我会从 AOSP 源码出发,把MediaPlayer.setScreenOnWhilePlaying从应用层一路拆到ViewRootImpl的 WakeLock,再结合我实际做过的一个视频播放器项目,讲清楚这套调用流程每个环节在干嘛、哪些地方容易踩坑,以及最后可复用的做法。这套链路从我实际验证过的 Android 14 到 Android 16 大版本,主线实现基本没有推翻,反而因为系统对亮屏资源管得越来越细,把这层封装搞明白的价值更大了。

1. 视频播放器屏幕常亮的三种做法:为什么最终都汇到 WakeLock

先聊一个根本问题:应用层想要“屏幕不灭”,到底有哪几条路?我在做播放器功能时,最常被问到的是这三个方案混着用,但很多人说不清它们的区别。

方案作用范围生命周期与播放状态绑定适合场景
android:keepScreenOn="true"(View 属性)单个 View / 所在 Window只要 View 在窗口上且属性存在就常亮无,需自行移除全屏图片、页面级常亮
PowerManager.WakeLock全局电源状态手动 acquire / release,必须成对无,要自己监听播放回调前后台混合的复杂任务
MediaPlayer.setScreenOnWhilePlaying播放器所在的 SurfaceHolder / Window跟随你传入的布尔值,并受播放器生命周期兜底语义上与播放相关,但不完全自动标准视频播放器、直播播放

表格里最关键的一行是“与播放状态绑定:不完全自动”。很多人以为调了setScreenOnWhilePlaying(true)之后,播放器暂停或释放就会自动去把屏幕状态还原,这是这篇最想纠正的误解。后面第 4 部分我会专门展开。

再往下挖一层,这三种方案在系统底层并不是完全平行的三条路。android:keepScreenOn会在遍历 View 树时把状态汇总到窗口,setScreenOnWhilePlaying走的是 SurfaceHolder 到 View 再到窗口的同一套汇总逻辑,而PowerManager.WakeLock更是直接作用于电源服务。它们的共同点是:屏幕要一直亮着,最终必须有东西在电源管理层面持有一把唤醒锁。只是有的方案帮你持了,有的方案要你自己持。

理解了这个公共归宿,你再看这三个方案的心态就不一样了:你关心的不再是“用哪个 API”,而是“谁负责申请这把锁、谁负责释放、锁的生命周期是否和我播放器的生命周期对齐”。setScreenOnWhilePlaying的价值就在于,它把“申请锁”的操作隐藏在 MediaPlayer 的封装里,并且在setDisplay时会自动同步状态。但释放的条件并没有你想象的那么智能,这一点是理解整个调用链的前提。

2. 调用链逐层拆解:从 MediaPlayer 到 ViewRootImpl 的一步一脚印

我把 AOSP 里这条调用链的关键源码片段拿出来走一遍。这套逻辑我从 Android 8 时代看到现在,主线一直是这个结构,没有大改。

2.1 入口:MediaPlayer.setScreenOnWhilePlaying 的校验与状态保存

MediaPlayer.java里的实现非常朴素,核心就是一个状态去重加一个校验:

// MediaPlayer.java (AOSP) public void setScreenOnWhilePlaying(boolean screenOn) { if (mScreenOnWhilePlaying != screenOn) { if (screenOn && mSurfaceHolder == null) { throw new IllegalStateException( "setScreenOnWhilePlaying requires a SurfaceHolder"); } mScreenOnWhilePlaying = screenOn; updateSurfaceScreenOn(); } }

两件事值得注意。第一,mScreenOnWhilePlaying != screenOn这个去重条件会让重复调用直接短路,不会产生多余的系统调用。第二,只有当你要设置 true 且当前没有 SurfaceHolder 时才会抛异常;如果你设置的是 false,即使 holder 为 null 也不会炸。这个细节在实战里很有用,第 3 部分我会拿它说事儿。

设置完标志位之后,紧接着调updateSurfaceScreenOn(),这个私有方法是整条链路的真实转发点:

private void updateSurfaceScreenOn() { if (mSurfaceHolder != null) { mSurfaceHolder.setKeepScreenOn(mScreenOnWhilePlaying); } }

那mSurfaceHolder从哪来?在播放器上,你必须把 SurfaceHolder 交给 MediaPlayer,它才会知道往哪块 Surface 上画视频。对应的方法是setDisplay(SurfaceHolder):

public void setDisplay(SurfaceHolder sh) { mSurfaceHolder = sh; setVideoSurfaceLocked(sh != null ? sh.getSurface() : null); updateSurfaceScreenOn(); }

这里有个容易被忽略的好消息:调用顺序其实不用太纠结。你完全可以先setScreenOnWhilePlaying(true)再setDisplay(holder),因为setDisplay最后一行会再次调用updateSurfaceScreenOn(),把你之前设置好的常亮状态补同步过去。反过来,先setDisplay再setScreenOnWhilePlaying(true)也没问题,后者的updateSurfaceScreenOn()直接就生效了。

2.2 中转:SurfaceHolder 只是桥梁,真正的接收方是 View

接下来看SurfaceHolder.setKeepScreenOn(boolean)的实现。注意SurfaceHolder是个接口,真正的实现在SurfaceView内部一个叫SurfaceHolderImpl的匿名类里。它的setKeepScreenOn实现相当直接:

// SurfaceView.java (AOSP,内部实现) public void setKeepScreenOn(boolean screenOn) { mView.setKeepScreenOn(screenOn); }

mView指的就是SurfaceView自己。换句话说,SurfaceHolder 在这里就只是个传话筒:MediaPlayer 说“我要屏幕常亮”,它把这句话原封不动转给了 SurfaceView 这个 View 对象。

转到 View 之后,View.setKeepScreenOn(true)会更新 View 的一个私有标志位,并且尝试在 AttachInfo 里汇报状态。AttachInfo是 View 和窗口之间的连接信息,这里面保存着当前窗口是否需要保持屏幕常亮。最终这个汇总工作会通知到ViewRootImpl:

// View.java (AOSP,核心逻辑摘录) public void setKeepScreenOn(boolean keepScreenOn) { // 更新 mPrivateFlags 中的 PFLAG_KEEP_SCREEN_ON ... updateKeepScreenOn(); } private void updateKeepScreenOn() { if (mAttachInfo != null) { // 把结果同步到 AttachInfo,并通知 ViewRootImpl 重新评估 ... } }

到这里为止,MediaPlayer 已经完全退场了。从 MediaPlayer 的角度看,它的任务就是把自己的mScreenOnWhilePlaying状态翻译成 View 的setKeepScreenOn。至于屏幕最后亮没亮,它并不直接关心。

2.3 终点:ViewRootImpl 持锁,屏幕才真正常亮

ViewRootImpl 是 View 和 WindowManager 之间的调度中枢。它初始化的时候会创建一个用于屏幕常亮的唤醒锁,这个锁的 tag 在 AOSP 里非常有辨识度:

// ViewRootImpl.java (AOSP) mScreenOnWakeLock = mPowerManager.newWakeLock( PowerManager.FULL_WAKE_LOCK, "ViewRootIml:SuspendScreenOn");

注意这个 tag 字符串,源码里一直是这样拼的,少了一个字母 i。你在dumpsys power输出里见到它,就能确定是 ViewRootImpl 的屏幕常亮机制在工作,不是某个三方库乱创建的锁。

在每次 performTraversals 的调度过程中,ViewRootImpl 会比较mAttachInfo.mKeepScreenOn和上次记录的mLastKeepScreenOn,一旦发现窗口有任何一个 View 申请了常亮,它就 acquire 这把锁;一旦窗口所有 View 都撤掉了常亮标记,它就 release:

// ViewRootImpl.java (AOSP,核心逻辑摘录) boolean keepScreenOn = mAttachInfo.mKeepScreenOn; if (keepScreenOn != mLastKeepScreenOn) { if (keepScreenOn) { mScreenOnWakeLock.acquire(); } else { mScreenOnWakeLock.release(); } mLastKeepScreenOn = keepScreenOn; }

到这里,整条调用链就闭合了。我把完整链路用文字捋一遍,这比图更耐看:

  1. 应用调用MediaPlayer.setScreenOnWhilePlaying(true)
  2. MediaPlayer 保存标志位并调用updateSurfaceScreenOn()
  3. mSurfaceHolder.setKeepScreenOn(true)转发到 SurfaceView
  4. View.setKeepScreenOn(true)更新 View 标志位并通知 AttachInfo
  5. ViewRootImpl 在窗口调度中看到常亮请求
  6. PowerManager.WakeLock.acquire(),电源服务收到持锁申请
  7. 屏幕保持点亮,不再进入熄屏流程

反向操作setScreenOnWhilePlaying(false)则是逐步释放锁的过程。这套链路如果你在日志、电源 dump 里逐一验证过,会非常有安全感。

2.4 一个关键结论:Java 层根本没走 JNI 控制屏幕

很多人一听 “MediaPlayer 的方法”,直觉认为底层肯定走 JNI 到 Native 播放引擎去控制 Surface。实际上不是。setScreenOnWhilePlaying整个 Java 调用链都没有进入native_方法,它是通过 View 体系的窗口常亮标记去申请唤醒锁的。Native 播放引擎只负责把视频帧画到 Surface 上,至于屏幕亮度策略,那是窗口系统的事。

这个结论解释了为什么当你使用TextureView时这个方法会失效:因为TextureView没有提供SurfaceHolder,MediaPlayer 内部的mSurfaceHolder是 null,压根走不到 ViewRootImpl 那一步。第 3 部分会细说。

3. 老项目里真实踩过的坑:明明设了 true,屏幕为什么还是灭了

看完源码,很多“反常现象”其实都能解释清楚了。我把实战中遇到过的几个典型问题整理成排查记录,每个都是线上真实场景,不是理论推演。

3.1 坑一:为了性能改用 TextureView,屏幕常亮彻底失效

短视频项目早期为了追求一些文字叠加动画效果,把播放器的承载 View 从 SurfaceView 换成了 TextureView。结果 QA 报了一个 bug:播放视频 30 秒后屏幕自动熄灭。

排查时最直接的现象是:调用setScreenOnWhilePlaying(true)直接抛了IllegalStateException: setScreenOnWhilePlaying requires a SurfaceHolder。原因很简单,MediaPlayer 的mSurfaceHolder没有被设置过。TextureView的 Surface 是通过setSurface(Surface)传出去的,它压根没有SurfaceHolder这个概念。

解决方案是绕开 MediaPlayer 的封装:

textureView.setKeepScreenOn(true); // 直接对 View 设置常亮标记

这行代码和MediaPlayer.setScreenOnWhilePlaying(true)走的是同一条 ViewRootImpl 持锁链路,只是少了 MediaPlayer 这一层中转。如果你的播放器使用了 TextureView,请记住这个替代方案,不要死磕 MediaPlayer 的 API。

3.2 坑二:SurfaceHolder 还没创建就 setDisplay,常亮状态丢在窗口 attach 之前

还有一例是横竖屏切换时,屏幕总是会在切换后的前几秒灭一下。现场代码是这样的:Activity 在onCreate里就准备播放器,然后立即调setScreenOnWhilePlaying(true)和setDisplay(holder)。但SurfaceView的 Surface 此时可能还没真正创建,surfaceCreated回调还没来。

从源码看,setDisplay把 holder 存进了 MediaPlayer,状态也同步给了 SurfaceView 的 View。可是如果窗口此时还没把 Surface 准备好,ViewRootImpl 的常亮判定仍然基于 AttachInfo 的当前状态。一旦后续 Surface 重建、窗口重新布局,旧的常亮请求可能不会自动重放。

这个问题的稳妥解法是:把setDisplay和setScreenOnWhilePlaying的调用都放在SurfaceHolder.Callback.surfaceCreated里,不要在onCreate里凭感觉提前绑。我在项目里是这么写的:

@Override public void surfaceCreated(SurfaceHolder holder) { if (mPlayer != null) { mPlayer.setScreenOnWhilePlaying(true); mPlayer.setDisplay(holder); } }

先设 true 再 setDisplay 完全没问题,因为setDisplay末尾的updateSurfaceScreenOn()会把 true 的状态同步过去。关键是保证绑定发生在 Surface 真正可用的窗口生命周期内。

3.3 坑三:暂停播放后屏幕依然常亮,锁没有被自动释放

这是我认为最容易被误解的一个地方。源码里setScreenOnWhilePlaying根本没有监听播放状态,也没有在暂停、播放完成、Seek 的时机去自动调整任何东西。它的作用就是“你让我亮,我就亮”,唯一能撤销这个动作的,只有你再次调用setScreenOnWhilePlaying(false),或者播放器走到reset/release的特定生命周期。

所以用户暂停视频想聊个天,如果 Activity 还在前台、窗口还活着,屏幕会一直亮着。对于手机端播放器来说,这通常不是你想要的行为。你需要在暂停时显式关闭:

mPlayer.pause(); mPlayer.setScreenOnWhilePlaying(false);

恢复播放时再开回来。这里有个细节值得注意:surfaceDestroyed回调里可以放心调用setScreenOnWhilePlaying(false),因为前面源码说过,false 分支不会因为 holder 为 null 抛异常。它可能拿不到 holder 直接跳过,但至少不会让 App 崩溃。

3.4 坑四:和 VideoView 混用时,你以为没生效,其实它内部早就做了

项目初期简单接了个VideoView做验证,发现自己在 Activity 里调setScreenOnWhilePlaying(true)后屏幕常亮正常。后来把 VideoView 换成自定义组件,又发现不生效了。

原因出在VideoView内部:它本来就是 MediaPlayer 加 SurfaceView 的状态机封装,源码里已经调用了setScreenOnWhilePlaying(true)。你外面再调一次只是重复设置,自然看起来“一切正常”。换成自定义组件后,如果你用的承载 View 不是 SurfaceView,或没有正确绑定 holder,问题立刻暴露。

所以排查屏幕常亮问题时,先搞清楚播放器组件内部有没有自己处理过。这个顺序错了会浪费不少时间。

3.5 实用的排查链路:用 dumpsys 验证锁到底被谁持有

遇到屏幕常亮异常,别只靠肉眼盯屏幕,直接看系统的电源管理状态。播放器正在播放时执行:

adb shell dumpsys power | grep -i wake

正常的话,你会在 WakeLock 列表里看到带ViewRootIml:SuspendScreenOn标签的锁。再配合窗口状态:

adb shell dumpsys window | grep -i keepScreenOn

窗口属性里也能看到常亮标记。如果dumpsys power里有锁、dumpsys window里没有,说明状态不同步,问题很可能出在 View 没有正确 attach;如果两处都没有,说明 MediaPlayer 压根没把状态发下去,要去查 holder 和控件类型。这套两步验证法,在大多数项目里都能一锤定音。

4. 实战接入:自定义播放器正确使用 setScreenOnWhilePlaying

之前做某个视频播放器 Demo 时,因为要控制渲染效果和生命周期,我没有直接用 VideoView,而是选了SurfaceView + MediaPlayer的自定义组合。这里把实战里的核心代码和设计理由完整分享出来。

4.1 播放器承载 View:在 surfaceCreated 里建立绑定

自定义一个PlayerSurfaceView,实现SurfaceHolder.Callback。最重要的就是surfaceCreated回调里的绑定逻辑:

public class PlayerSurfaceView extends SurfaceView implements SurfaceHolder.Callback { private MediaPlayer mPlayer; public PlayerSurfaceView(Context context) { super(context); getHolder().addCallback(this); } @Override public void surfaceCreated(SurfaceHolder holder) { if (mPlayer == null) { return; } // 先申请常亮标志,再绑定 SurfaceHolder mPlayer.setScreenOnWhilePlaying(true); mPlayer.setDisplay(holder); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { // 通常在 surfaceChanged 里做画面适配,这里略 } @Override public void surfaceDestroyed(SurfaceHolder holder) { // Surface 销毁,播放器通常进入 stopped / 释放流程 if (mPlayer != null) { mPlayer.setScreenOnWhilePlaying(false); } } public void setPlayer(MediaPlayer player) { mPlayer = player; } }

为什么要把setScreenOnWhilePlaying(true)放在surfaceCreated而不是onCreate?因为 SurfaceView 的 Surface 创建时机由 Window 管理,必须等surfaceCreated回调,Surface 才真正有效。在这个回调里绑定,可以避免 Surface 未就绪导致的窗口状态不同步问题,也就是第 3 部分的坑二。

4.2 播放控制层:显式管理暂停、恢复和释放时的屏幕状态

接下来是播放控制层。核心原则一句话:setScreenOnWhilePlaying不是自动的,你要在播放语义切换的时候显式跟着切。下面的伪代码展示了一个最小可用状态管理:

public class PlayerController { private MediaPlayer mPlayer; private PlayerSurfaceView mSurfaceView; public void play(String url) { if (mPlayer == null) { mPlayer = new MediaPlayer(); mSurfaceView.setPlayer(mPlayer); } // 先准备好再开始,一旦开始播放就申请屏幕常亮 mPlayer.setOnPreparedListener(mp -> { mp.start(); mp.setScreenOnWhilePlaying(true); }); // ... 省略 setDataSource、prepare 等步骤 } public void pause() { if (mPlayer != null && mPlayer.isPlaying()) { mPlayer.pause(); // 暂停时主动撤销常亮,让系统可以正常熄屏 mPlayer.setScreenOnWhilePlaying(false); } } public void resume() { if (mPlayer != null && !mPlayer.isPlaying()) { mPlayer.start(); mPlayer.setScreenOnWhilePlaying(true); } } public void release() { if (mPlayer != null) { mPlayer.setScreenOnWhilePlaying(false); mPlayer.release(); mPlayer = null; } } }

注意我在pause()里显式调了 false,这正好补上了源码不会自动做的释放动作。实际项目中,暂停后通常还希望屏幕继续亮(比如用户可能在做笔记),这个策略完全可以做成可配置的,但核心思想是一样的:你的播放状态机里每个切换点,都要思考常亮标志是否要跟着变。

4.3 页面生命周期兜底:onPause 里一定要清掉常亮

还有一个我在真实项目中见过的高频 bug:用户切到后台找别的 App 聊天,回来发现一个多小时的电量被这个播放器耗掉了。原因就是播放器在后台继续运行,屏幕常亮锁没有被释放,屏幕虽然是灭的,但系统电源状态一直以为有画面在呈现。

无论你的播放器如何处理后台播放,页面级生命周期必须做兜底:

@Override protected void onPause() { super.onPause(); if (mPlayerController != null) { mPlayerController.release(); } } @Override protected void onResume() { super.onResume(); // 回到前台再重新初始化播放器,恢复播放 if (mPlayerController != null && shouldResumePlayback) { mPlayerController.play(mCurrentUrl); } }

onPause里调用release而不是只 pause,是我个人比较推荐的做法。MediaPlayer.release()会释放底层资源,同时把常亮状态清理干净。如果你的场景必须保持后台播放,那至少也要把setScreenOnWhilePlaying(false)调掉,不要让后台播放继续锁住屏幕——后台播放本身不需要画面常亮。

4.4 横竖屏与多窗口切换的兜底逻辑

Android 大版本上横竖屏切换默认会重建 Activity,Surface 会经历销毁到重建的过程。我在项目里遇到过切换后常亮失效的问题,最后定位到就是surfaceCreated里没有重新绑定。

处理方式是在 Activity 重建后,确保播放器重新走一遍play()流程,让surfaceCreated回调再次触发绑定。如果你的播放器支持同 Activity 内的横竖屏不重建,也要在surfaceChanged里检查当前常亮标志是否仍然有效:

@Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { // 某些 ROM 在横竖屏切换后可能没有重新触发 surfaceCreated, // 这里做一次兜底同步 if (mPlayer != null && isPlaybackActive) { mPlayer.setScreenOnWhilePlaying(true); mPlayer.setDisplay(holder); } }

这个操作本质上是把setDisplay的同步能力再向 Surface 重建场景延伸了一次,很稳妥。

5. 从 Framework 层验证调用链:设备上直接观察,不靠猜

这个调用链讲完,你可以不只在代码层面相信它,在真实设备上是可以验证的。我习惯用一组命令确认自己写的代码真的走到了 ViewRootImpl 的持锁分支。

5.1 先看电源服务里的锁

播放器处于播放状态时:

adb shell dumpsys power | grep -A 30 "Wake Locks"

输出里应该能看到类似这样的行:

Wake Locks: window: ViewRootIml:SuspendScreenOn (full)

这个ViewRootIml:SuspendScreenOn就是源码里那个少一个字母 i 的 tag。看到它,说明整条 View 链路已经生效。如果没看到,继续下一步。

5.2 再看窗口属性

adb shell dumpsys window | grep -i keepScreenOn

如果窗口已经携带常亮标记,这里会显示相关字段。窗口有标记、电源无锁,大概率是窗口还没把请求下发到 ViewRootImpl 的持锁逻辑,属于状态同步的中间态;窗口无标记,则回到第 3 部分的坑去找控件类型和绑定顺序。

5.3 必要时开启帧渲染日志

如果前两步还定位不到问题,我会在播放器线程打开帧渲染状态追踪,观察 Surface 合成期间屏幕状态切换。这里不展开具体参数了,实际项目里我用得最多的还是dumpsys power加应用日志双端对齐:应用代码在setScreenOnWhilePlaying调用前后各打一条日志,系统侧同步拉取dumpsys power,几乎能精确到是哪一层吞掉了状态。

这套验证方法我在多个机型上试过,包括一些深度定制的 ROM,结论高度一致:只要控件是 SurfaceView,绑定时机正确,setScreenOnWhilePlaying在这条链路里都是可靠的。如果哪天发现它失效,优先怀疑自己的绑定时机,而不是怀疑系统实现。

6. 高版本大版本适配的个人经验:别把常亮资源撒得到处都是

最后聊聊 Android 16 这个题眼。我在验证这套逻辑时,看到的是近几个大版本并没有推翻setScreenOnWhilePlaying的实现主线,但它所在的电源管理领域变化很多。系统对长时间持有唤醒锁、对屏幕常亮资源的使用,越来越强调“声明清晰、释放及时”。

我自己的经验是:把屏幕常亮当作播放器的一个可释放状态位来管理,而不是一个一劳永逸的配置。不管未来 Android 大版本怎么演进,下面几条习惯都不会过时。

第一条,常亮状态和播放状态必须由同一个控制器管理,不要把setScreenOnWhilePlaying散落在 Activity、Fragment、View 的各个回调里。当代码里只有一个入口能修改常亮标志位时,出问题就好查了。

第二条,释放路径永远要比申请路径更保守。申请可以在 surfaceCreated、播放恢复、横竖屏切换成功后进行;释放则要覆盖 pause、release、onPause、surfaceDestroyed 至少四个时机。源码不帮你自动释放暂停状态,这个兜底只能你自己做。

第三条,reset()之后要重新评估常亮状态。MediaPlayer 的reset()会让播放器回到初始状态,但 View 那边的常亮标志未必同步清理。在我的项目里,所有重置播放器的逻辑都会先调一次setScreenOnWhilePlaying(false),再走重新初始化流程。

第四条,如果播放器栈迁移到 ExoPlayer,setScreenOnWhilePlaying这个 API 就没有了,需要换成PlayerView.setKeepScreenOn(true)或直接对承载 View 设置常亮标记。但底层走的路依然是 ViewRootImpl 到ViewRootIml:SuspendScreenOn这把锁,理解了这个公共归宿,你在任何播放器框架之间切换都不会慌。

最后分享一个我常跟同事说的小技巧:在dumpsys power的 WakeLock 列表里,如果同时看到几个不同的 tag,花一点时间把它们全部解析出来——它们代表了当前窗口里所有常亮请求的完整来源。我曾经排查过一个“播放器关闭后屏幕依然常亮”的问题,最后发现是另一个全屏广告容器也申请了常亮,调用链完全独立,但表现和播放器问题一模一样。把这些资源都盘清楚,才是多媒体开发的基本功。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/15 9:17:48

大模型推理性能瓶颈:CUDA、Triton与torch.compile选型实战指南

1. 项目概述:为什么“大模型算子框架选型”不是技术选型题,而是工程生死线“大模型算子框架选型”这八个字,听上去像一个技术评审会上的PPT小节标题,但在我过去三年深度参与六个千卡级大模型推理平台建设、亲手调优过从A100到H100…

作者头像 李华
网站建设 2026/10/15 9:16:27

Java线程等待与通知机制详解

1. 线程等待与通知机制概述在并发编程中,线程间的协调是保证程序正确性的关键。当多个线程需要按照特定顺序执行或共享资源时,单纯的锁机制往往不够高效。Java内置的等待/通知机制(wait/notify)提供了一种线程间通信的优雅解决方案…

作者头像 李华
网站建设 2026/10/15 9:15:57

PPT翻页背后:从ISA到中断的软硬件协作全链路解析

你大概率被人问过这句话:请描述一下PPT完成翻页时,电脑软硬件是如何协作的。别小看它,它把一个通用计算机最关键的“输入—处理—输出”全链路都卷了进来。这一问之所以经典,一方面是因为它横跨操作系统、计算机体系结构、编译原理…

作者头像 李华
网站建设 2026/10/15 9:15:53

2026年CCF期刊目录更新:AI与网络安全领域重大调整

1. 2026年CCF期刊目录更新解读今天上午,中国计算机学会(CCF)正式发布了2026年版推荐期刊目录,这是继2023年更新后的又一次重要调整。作为计算机领域科研工作者最关注的学术评价标准之一,这份目录直接影响着国内高校和研…

作者头像 李华
网站建设 2026/10/15 9:15:50

两周建起数据资产目录:轻量元数据采集+人工校验实战

简介:本资源是一份聚焦华为数据治理实践的深度学习分享材料,面向数据工程师、企业数字化转型从业者及数据中台建设相关人员,旨在系统解析华为数据之道的方法论框架与落地路径。文件为单页PDF(4.8MB),内容凝…

作者头像 李华
网站建设 2026/10/15 9:14:50

北京都市人群营养自愈力实践指南

1. 项目背景与核心理念在北京这座快节奏的都市里,越来越多的人开始关注通过自然方式提升健康水平。营养自愈力这个概念,简单来说就是通过科学调整饮食结构和生活方式,激发人体与生俱来的自我修复能力。过去三年里,我和团队成员在朝…

作者头像 李华