线程的状态转换和调度

embedded/2025/2/3 15:56:10/

  1. 新建状态New:新创建了一个线程对象

  2. 可运行状态Runnable:线程对象创建后,其他线程调用了该对象的start()方法。该状态的线程位于可运行线程池中,变得可运行,等待获取CPU的使用权。

  3. 运行状态Running:可运行状态的线程获取了CPU资源时,执行程序run()方法代码。

  4. 阻塞状态Blocked:线程由于某种原因放弃CPU使用权,暂时停止运行。阻塞的情况分两种种:

    1. 同步阻塞:对象的同步锁被其他的线程占用时,则JVM会把该线程放入锁池中等待锁释放。

    2. 其他阻塞:当运行的线程执行sleep()join()方法,或发起I/O请求时,该线程将进入阻塞状态。在此期间,线程不会释放已持有的锁,一旦 sleep() 调用完成、join() 方法的等待线程终止或超时,或者 I/O 操作完成,线程将返回到可运行状态

  5. Waiting(等待状态): 运行的线程执行wait()方法,JVM会把该线程放入等待池中。需要被显式唤醒才能继续执行。

  6. Timed Waiting(含等待时间的等待状态): 线程进入等待状态,但指定了等待时间,超时后会被唤醒

  7. 终止状态(Terminated):线程正常完成了run() 方法执行流程 或 异常而提前退出时,该线程结束生命周期。

线程的调度
  1. 调整线程优先级:Java线程有优先级,且有继承关系(如A线程中创建B线程,AB优先级一样),优先级高的线程可能更先运行

static int MAX_PRIORITY线程可以具有的最高优先级,取值为10。
static int MIN_PRIORITY线程可以具有的最低优先级,取值为1。
static int NORM_PRIORITY分配给线程的默认优先级,取值为5。
  1. 线程睡眠:Thread.sleep(long millis)方法,使线程转到阻塞状态。millis参数设定睡眠的时间,以毫秒为单位。当睡眠结束后,就转为可运行状态 ,sleep() 方法的实现是平台无关的,可以在不同的操作系统上正常工作

  2. 线程等待:调用Object.wait()方法,释放了当前线程持有的对象锁,并将线程放入等待池中,直到其他线程调用此对象锁(Object)的notify()notifyAll()方法唤醒 等待池中的一个或多个对象

    • 如果多个线程都在等待同一个对象锁,则 notify() 方法只会唤醒其中一个线程,而 notifyAll() 则会唤醒所有等待中的线程,重新竞争该对象的锁

  3. 线程让步:调用Thread.yield()方法,让当前运行线程回到可运行状态,把执行机会让给自己,相同或者更高优先级的线程

  4. 线程加入:调用Thread.join()方法,可以让当前线程等待另一个线程的终止。即在当前线程中调用另一个线程的 join() 方法,当前线程将会进入阻塞状态,直到另一个线程运行结束,然后恢复到可运行状态

  5. 线程唤醒:调用 Object.notify() 方法,可以唤醒一个在该对象上等待的线程。如果多个线程都在等待同一个监视器,则 notify() 方法会随机选择一个线程来唤醒。。而 notifyAll() 方法则会唤醒所有在该对象监视器上等待的线程,被唤醒的线程需要重新竞争对象锁才能继续执行。

例子说明

注意点

  • wait,notify和 notifyAll 只能在同步锁方法或者同步控制块里面使用,而sleep可以在任何地方使用

  • 当线程离开一个同步块后,会自动释放该同步块持有的锁,这是Java规范

//wait用法
public class MyThreadPrinter2 implements Runnable {   private String name;   private Object prev;   private Object self;   private MyThreadPrinter2(String name, Object prev, Object self) {this.name = name; this.prev = prev;this.self = self;}   
​@Override  public void run() {   int count = 10;   while (count > 0) {   synchronized (prev) {     //先持有前一个线程所持有的对象锁前提下 synchronized (self) {      //持有自身对象锁      System.out.print(name);   count--;           self.notify();   //唤醒一个在当前对象上等待的线程  }   //自动释放self锁try {   prev.wait();     //释放prev对象锁,终止该锁上的当前线程} catch (InterruptedException e) {   e.printStackTrace();   }   }   }     public static void main(String[] args) throws Exception {   Object a = new Object();   Object b = new Object();   Object c = new Object();   MyThreadPrinter2 pa = new MyThreadPrinter2("A", c, a);  MyThreadPrinter2 pb = new MyThreadPrinter2("B", a, b);  MyThreadPrinter2 pc = new MyThreadPrinter2("C", b, c);         //整体过程//A线程最先运行,持有c,a对象锁-->唤醒B-->释放a锁-->释放c锁//线程B持有a,b锁,执行同步代码块后-->唤醒C-->释放b锁-->释放a锁//线程C持有b,c锁,执行同步代码块后-->唤醒A-->释放c锁-->释放b锁new Thread(pa).start();Thread.sleep(100);       //确保按顺序A、B、C执行new Thread(pb).start();Thread.sleep(100);  new Thread(pc).start();   Thread.sleep(100);  }   
}  
//输出结果:
//ABCABCABCABCABCABCABCABCABCABC


http://www.ppmy.cn/embedded/159216.html

相关文章

Redisson分布式限流的使用及原理

1. 常见的分布式限流算法 1.1 固定窗口算法 原理:固定窗口算法是一种简单的限流算法。在固定时间窗口内,记录请求的数量。例如,设定每10秒钟最多允许5次请求,如果在当前窗口内的请求数超过限制,则拒绝请求。 优点&a…

flowable expression和json字符串中的双引号内容

前言 最近做项目,发现了一批特殊的数据,即特殊字符",本身输入双引号也不是什么特殊的字符,毕竟在存储时就是正常字符,只不过在编码的时候需要转义,转义符是\,然而转义符\也是特殊字符&…

探索 Copilot:开启智能助手新时代

探索 Copilot:开启智能助手新时代 在当今数字化飞速发展的时代,人工智能(AI)正以前所未有的速度改变着我们的工作和生活方式。而 Copilot 作为一款强大的 AI 助手,凭借其多样的功能和高效的应用,正在成为众…

web前端12--表单和表格

1、表格标签 使用<table>标签来定义表格 HTML 中的表格和Excel中的表格是类似的&#xff0c;都包括行、列、单元格、表头等元素。 区别&#xff1a;HTML表格在功能方面远没有Excel表格强大&#xff0c;HTML表格不支持排序、求和、方差等数学计算&#xff0c;主要用于布…

Flutter子页面向父组件传递数据方法

在 Flutter 中&#xff0c;如果父组件需要调用子组件的方法&#xff0c;可以通过以下几种方式实现。以下是常见的几种方法&#xff1a; 方法 1&#xff1a;使用 GlobalKey 和 State 调用子组件方法 这是最直接的方式&#xff0c;通过 GlobalKey 获取子组件的 State&#xff0c…

DeepSeek-R1 论文解读 —— 强化学习大语言模型新时代来临?

近年来&#xff0c;人工智能&#xff08;AI&#xff09;领域发展迅猛&#xff0c;大语言模型&#xff08;LLMs&#xff09;为通用人工智能&#xff08;AGI&#xff09;的发展开辟了道路。OpenAI 的 o1 模型表现非凡&#xff0c;它引入的创新性推理时缩放技术显著提升了推理能力…

(undone) MIT6.S081 2023 学习笔记 (Day7: LAB6 Multithreading)

网页&#xff1a;https://pdos.csail.mit.edu/6.S081/2023/labs/thread.html 任务1&#xff1a;Uthread: switching between threads (moderate) (doing) 在这个练习中&#xff0c;你将设计一个用户级线程系统中的上下文切换机制&#xff0c;并实现它。为了帮助你开始&#xf…

蓝桥杯之c++入门(四)【循环】

目录 前言6. while循环6.1 while语法形式6.2 执行流程6.3 实践6.4 练习练习1&#xff1a;反向输出每一位练习2&#xff1a;数位之和练习3&#xff1a;求和1练习4&#xff1a;含 k 个 3 的数练习5&#xff1a;角谷猜想练习6&#xff1a;计算多项式的值 7. for循环7.1 for循环语法…