sleep和yield区别

本文详细解析了Java中线程控制的关键方法,如sleep、yield、wait与notify等的区别及应用场景,探讨了volatile语义及数据同步机制。
部署运行你感兴趣的模型镜像

  sleep和yield区别:

  1、sleep()方法会给其他线程运行的机会,而不考虑其他线程的优先级,因此会给较低线程一个运行的机会;yield()方法只会给相同优先级或者更高优先级的线程一个运行的机会。

  2、当线程执行了sleep(long millis)方法后,将转到阻塞状态,参数millis指定睡眠时间;当线程执行了yield()方法后,将转到就绪状态。

  3、sleep()方法声明抛出InterruptedException异常,而yield()方法没有声明抛出任何异常

  4、sleep()方法比yield()方法具有更好的移植性

  如果希望明确地让一个线程给另外一个线程运行的机会,可以采取以下的办法之一:

  1、调整各个线程的优先级

  2、让处于运行状态的线程调用Thread.sleep()方法

  3、让处于运行状态的线程调用Thread.yield()方法

  4、让处于运行状态的线程调用另一个线程的join()方法

  首先,wait()和notify(),notifyAll()是Object类的方法,sleep()和yield()是Thread类的方法。

  (1)。常用的wait方法有wait()和wait(long timeout):

  void wait() 在其他线程调用此对象的 notify() 方法或 notifyAll() 方法前,导致当前线程等待。

  void wait(long timeout) 在其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者超过指定的时间量前,导致当前线程等待。

  wait()后,线程会释放掉它所占有的"锁标志",从而使线程所在对象中的其它synchronized数据可被别的线程使用。

  wait()和notify()因为会对对象的"锁标志"进行操作,所以它们必须在synchronized函数或synchronized代码块中进行调用。如果在non- synchronized函数或non-synchronized代码块中进行调用,虽然能编译通过,但在运 行时会发生IllegalMonitorStateException的异常。

  (2)。Thread.sleep(long millis),必须带有一个时间参数。

  sleep(long)使当前线程进入停滞状态,所以执行sleep()的线程在指定的时间内肯定不会被执行;

  sleep(long)可使优先级低的线程得到执行的机会,当然也可以让同优先级和高优先级的线程有执行的机会;

  sleep(long)是不会释放锁标志的。

  (3)。yield()没有参数。

  sleep 方法使当前运行中的线程睡眼一段时间,进入不可运行状态,这段时间的长短是由程序设定的,yield 方法使当前线程让出CPU占有权,但让出的时间是不可设定的。yield()也不会释放锁标志。

  实际上,yield()方法对应了如下操作: 先检测当前是否有相同优先级的线程处于同可运行状态,如有,则把 CPU 的占有权交给此线程,否则继续运行原来的线程。所以yield()方法称为"退让",它把运行机会让给了同等优先级的其他线程。

  sleep方法允许较低优先级的线程获得运行机会,但yield()方法执行时,当前线程仍处在可运行状态,所以不可能让出较低优先级的线程些时获得CPU占有权。 在一个运行系统中,如果较高优先级的线程没有调用 sleep 方法,又没有受到 I/O阻塞,那么较低优先级线程只能等待所有较高优先级的线程运行结束,才有机会运行。

  yield()只是使当前线程重新回到可执行状态,所以执行yield()的线程有可能在进入到可执行状态后马上又被执行。所以yield()只能使同优先级的线程有执行的机会。

  volitile 语义

  volatile相当于synchronized的弱实现,也就是说volatile实现了类似synchronized的语义,却又没有锁机制。它确保对volatile字段的更新以可预见的方式告知其他的线程。

  volatile包含以下语义:

  (1)Java 存储模型不会对valatile指令的操作进行重排序:这个保证对volatile变量的操作时按照指令的出现顺序执行的。

  (2)volatile变量不会被缓存在寄存器中(只有拥有线程可见)或者其他对CPU不可见的地方,每次总是从主存中读取volatile变量的结果。也就是说对于volatile变量的修改,其它线程总是可见的,并且不是使用自己线程栈内部的变量。也就是在happens-before法则中,对一个valatile变量的写操作后,其后的任何读操作理解可见此写操作的结果。

  尽管volatile变量的特性不错,但是volatile并不能保证线程安全的,也就是说volatile字段的操作不是原子性的,volatile变量只能保证可见性(一个线程修改后其它线程能够理解看到此变化后的结果),要想保证原子性,目前为止只能加锁!

  数据同步:

  线程同步的特征:

  1、如果一个同步代码块和非同步代码块同时操作共享资源,仍然会造成对共享资源的竞争。因为当一个线程执行一个对象的同步代码块时,其他的线程仍然可以执行对象的非同步代码块。(所谓的线程之间保持同步,是指不同的线程在执行同一个对象的同步代码块时,因为要获得对象的同步锁而互相牵制)

  2、每个对象都有唯一的同步锁

  3、在静态方法前面可以使用synchronized修饰符,但是要注意的是锁对象是类(用Object.class而不能用this),而不是这个类的对象。

  4、当一个线程开始执行同步代码块时,并不意味着必须以不间断的方式运行,进入同步代码块的线程可以执行Thread.sleep()或者执行Thread.yield()方法,此时它并不释放对象锁,只是把运行的机会让给其他的线程。

  5、synchronized声明不会被继承,如果一个用synchronized修饰的方法被子类覆盖,那么子类中这个方法不在保持同步,除非用synchronized修饰。

  6、synchronized 关键字能够修饰一个对象实例中的函数或者代码块。 在一个非静态方法中 this 关键字表示当前的实例对象。 在一个 synchronized 修饰的静态的方法中,这个方法所在的类使用 Class 作为实例对象

您可能感兴趣的与本文相关的镜像

Stable-Diffusion-3.5

Stable-Diffusion-3.5

图片生成
Stable-Diffusion

Stable Diffusion 3.5 (SD 3.5) 是由 Stability AI 推出的新一代文本到图像生成模型,相比 3.0 版本,它提升了图像质量、运行速度和硬件效率

### sleepyield区别与联系 在 Java 多线程编程中,`sleep` `yield` 是 `Thread` 类提供的两个用于控制线程执行的方法。它们在行为、状态转换、资源控制以及应用场景上存在显著差异。 #### 线程状态变化 - `sleep` 方法会使当前线程从运行状态(Running)进入阻塞状态(Blocked),在指定的时间内不会参与 CPU 的调度。时间结束后,线程会自动回到就绪状态(Runnable),等待调度器重新分配 CPU 时间[^3]。 - `yield` 方法则不会使线程进入阻塞状态,而是让出当前的 CPU 时间片,使线程重新回到就绪状态。线程会立即参与 CPU 时间的竞争,如果此时没有其他同优先级或更高优先级的线程等待,则该线程可能立刻被重新调度执行[^1]。 #### 优先级考虑 - `sleep` 方法不考虑线程优先级,所有线程都有机会获得 CPU 时间[^4]。 - `yield` 方法则会优先考虑同优先级或更高优先级的线程。 #### 是否释放锁资源 - 两者都不会释放线程持有的对象锁资源。这意味着在同步代码块或同步方法中调用 `sleep` 或 `yield`,线程仍然持有锁,其他线程无法进入该同步代码块[^2]。 #### 方法参数与异常 - `sleep` 方法具有参数,用于指定线程休眠的时间长度,在 `Thread` 类中有两种重载形式:`sleep(long millis)` `sleep(long millis, int nanos)`。该方法声明抛出 `InterruptedException`,因此在调用时需要处理或声明该异常[^4]。 - `yield` 方法没有参数,也不抛出任何异常,其行为由 JVM 实现决定。 #### 可移植性与适用性 - `sleep` 方法的行为在不同平台下较为一致,具有较好的可移植性。 - `yield` 方法的行为则可能因 JVM 实现操作系统调度策略的不同而有所差异,因此在跨平台应用中使用时需谨慎[^4]。 #### 应用场景 - `sleep` 常用于需要定时休眠的场景,例如定时任务、限流控制、模拟延迟等[^3]。 - `yield` 更适合用于线程调度优化,特别是在多个线程竞争 CPU 时间时,用于主动让出 CPU 以提升整体调度效率,尤其是在同优先级线程之间[^1]。 #### 示例代码 以下是一个简单的示例,展示 `sleep` `yield` 的使用方式: ```java public class SleepVsYield { public static void main(String[] args) { Thread sleepThread = new Thread(() -> { for (int i = 0; i < 5; i++) { System.out.println("Sleeping Thread: " + i); try { Thread.sleep(1000); // 线程休眠1秒 } catch (InterruptedException e) { e.printStackTrace(); } } }); Thread yieldThread = new Thread(() -> { for (int i = 0; i < 5; i++) { System.out.println("Yielding Thread: " + i); Thread.yield(); // 让出CPU } }); sleepThread.start(); yieldThread.start(); } } ``` ###
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值