线程的状态转换和调度

news/2025/2/3 17:01:13 标签: java, 开发语言

  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.niftyadmin.cn/n/5840928.html

相关文章

unity学习26:用Input接口去监测: 鼠标,键盘,虚拟轴,虚拟按键

目录 1 用Input接口去监测:鼠标,键盘,虚拟轴,虚拟按键 2 鼠标 MouseButton 事件 2.1 鼠标的基本操作 2.2 测试代码 2.3 测试情况 3 键盘Key事件 3.1 键盘的枚举方式 3.2 测试代码同上 3.3 测试代码同上 3.4 测试结果 4…

29.Word:公司本财年的年度报告【13】

目录 NO1.2.3.4 NO5.6.7​ NO8.9.10​ NO1.2.3.4 另存为F12:考生文件夹:Word.docx选中绿色标记的标题文本→样式对话框→单击右键→点击样式对话框→单击右键→修改→所有脚本→颜色/字体/名称→边框:0.5磅、黑色、单线条:点…

C#,shell32 + 调用控制面板项(.Cpl)实现“新建快捷方式对话框”(全网首发)

Made By 于子轩,2025.2.2 不管是使用System.IO命名空间下的File类来创建快捷方式文件,或是使用Windows Script Host对象创建快捷方式,亦或是使用Shell32对象创建快捷方式,都对用户很不友好,今天小编为大家带来一种全新…

012-51单片机CLD1602显示万年历+闹钟+农历+整点报时

1. 硬件设计 硬件是我自己设计的一个通用的51单片机开发平台,可以根据需要自行焊接模块,这是用立创EDA画的一个双层PCB板,所以模块都是插针式,不是表贴的。电路原理图在文末的链接里,PCB图暂时不选择开源。 B站上传的…

使用Z-score进行数据特征标准化

数据标准化是数据处理过程中非常重要的一步,尤其在构建机器学习模型时尤为关键。标准化的目的是将不同量纲的变量转换到相同的尺度,以避免由于量纲差异导致的模型偏差。Z-score标准化是一种常见且简单的标准化方法,它通过计算数据点与平均值的差异,并将其按标准差进行缩放,…

实现Ajax请求、实现深拷贝

文章目录 1 实现Ajax请求2 实现深拷贝2.1 方法1:JSON.stringify()2.2 方法2:函数库lodash的_.cloneDeep方法2.3 方法3:手写实现深拷贝函数 1 实现Ajax请求 Ajax(Asynchronous JavaScript and XML),是指通过…

#define,源文件与头文件,赋值表达式

1.#define 1.1定义 #define 是一个预处理指令,用于定义宏 宏,是预处理阶段(在编译之前)由预处理器处理的代码片段 1.2使用 1.2.1 #define 可以定义常量 #define PI 3.14159 1.2.2 #define 可以定义宏函数 #define SQUARE(x) ((…

ResNet--深度学习中的革命性网络架构

一、引言 在深度学习的研究和应用中,网络架构的设计始终是一个关键话题。随着计算能力和大数据的不断提升,深度神经网络逐渐成为解决复杂任务的主流方法。然而,随着网络层数的增加,训练深度神经网络往往面临梯度消失或梯度爆炸的…