(喜欢的觉得有用的家人们关注一下作者呗)

线程常用的调度方法可分为核心调度策略和线程协作控制方法两大类,前者决定CPU资源分配规则,后者用于线程间的等待、唤醒与状态控制。

一、核心调度策略(CPU分配规则)

    1.    非抢占式调度(协作式):线程需主动放弃CPU(如执行完任务、调用阻塞方法),其他线程才能执行,无强制切换机制,易导致“线程饥饿”。

    2.    抢占式调度:操作系统按优先级或时间片强制切换线程,高优先级线程可打断低优先级线程,能避免“饥饿”,是Windows、Linux等主流系统的默认方式。

可以用“食堂打饭”的场景类比,理解起来更直观:

    •    非抢占式调度:就像食堂只有1个窗口,且打饭规则是“谁先排到,就一次把饭打完、打够才走”。如果前面有人慢慢纠结菜品、反复加菜,后面的人只能一直等,直到前者主动结束打饭,下一个人才能上前。

以非抢占式调度的编程场景为例:早期的单任务操作系统(如DOS系统)中,若你同时运行“文本编辑”程序和“文件复制”程序,会遵循“谁先启动、谁用完CPU谁让”的规则。

假设你先打开“文本编辑”程序(先占用CPU),此时即便你再启动“文件复制”程序,“文件复制”也只能排队等待——只有当你主动关闭“文本编辑”程序(线程主动释放CPU),或者手动切换到“文件复制”并让其开始执行后,“文件复制”线程才能获得CPU资源,期间没有任何机制能强制“文本编辑”暂停并让出资源。

这种“线程不主动放手,其他线程就无法执行”的逻辑,就是非抢占式调度在编程中的典型体现。

    •    抢占式调度:类似食堂有“优先级规则”或“限时打饭”。比如老师(高优先级线程)来了可以直接插队先打;或者规定每个人最多只能打5分钟,时间一到不管有没有打完,都得让给下一个人,自己去队尾重新排队,能保证没人一直占着窗口。

以抢占式调度的编程场景为例:在手机的后台任务中,你同时开启了“音乐播放”(低优先级线程)和“微信视频通话”(高优先级线程)。

原本“音乐播放”线程在占用CPU资源发声,但当“微信视频通话”线程启动时,操作系统会判定其优先级更高,强制暂停“音乐播放”线程,将CPU资源抢占分配给“视频通话”线程,以保证通话的流畅性。当通话结束后,操作系统再把CPU资源还给“音乐播放”线程,让它继续播放音乐。

这种“高优先级任务打断低优先级任务”的逻辑,就是编程中抢占式调度的典型应用,能确保关键任务优先响应。

二、线程协作控制方法(Object/Thread类提供)

1. 线程等待与通知(基于共享对象锁,需在同步代码块中使用)

    •    等待方法(Object类):让当前线程阻塞,释放对象锁。

    ◦    wait():需被notify()/notifyAll()唤醒,或被中断(抛InterruptedException)才返回。

    ◦    wait(long timeout):超时后自动唤醒,无需外部通知。

    •    唤醒方法(Object类):唤醒在共享对象上等待的线程,不释放当前线程的锁。

    ◦    notify():随机唤醒1个等待线程。

    ◦    notifyAll():唤醒所有等待线程。

    •    线程等待(Thread类):join(),让当前线程等待目标线程执行完毕后再继续,如线程A调用threadB.join(),A会阻塞到B结束。

2. 线程休眠(Thread类静态方法)

    •    sleep(long millis):让线程暂时让出CPU,不释放锁,休眠时间到后重新参与CPU调度;可被interrupt()中断(抛InterruptedException)。

3. 让出CPU(Thread类静态方法)

    •    yield():暗示调度器让出当前CPU,仅为“建议”,调度器可忽略;不释放锁,线程仍处于就绪状态,会快速重新参与竞争。

4. 线程中断(协作式中断,非强制终止)

    •    interrupt():设置线程的“中断标志”,不直接终止线程,需线程自行检测标志并处理。

    •    isInterrupted():检测线程的中断标志,不清除标志。

    •    interrupted():检测当前线程的中断标志,会清除标志(连续调用第二次返回false)。

 

 

更多推荐