java中线程的sleep()方法和yield()方法的区别

 更新时间:2024年10月23日 10:29:31   作者:Flying_Fish_Xuan  
本文主要介绍了java中线程的sleep()方法和yield()方法的区别,Thread类的sleep()方法使线程休眠指定时间,不释放锁,而yield()提示调度器当前线程愿意让出CPU资源,不保证立即切换线程,感兴趣的可以了解一下

1. sleep()方法

1.1 sleep()方法的定义

sleep()方法是Thread类的一个静态方法,用于使当前线程进入休眠状态(阻塞状态)一段指定的时间。在此期间,线程会暂停执行并让出CPU资源给其他线程。休眠时间结束后,线程会自动从休眠状态恢复到可运行状态(Runnable),等待操作系统重新调度。

sleep()方法有两个重载版本:

public static void sleep(long millis) throws InterruptedException;
public static void sleep(long millis, int nanos) throws InterruptedException;
  • 第一个方法使线程休眠指定的毫秒数。
  • 第二个方法使线程休眠指定的毫秒数和额外的纳秒数。

1.2 sleep()方法的工作原理

当线程调用Thread.sleep()时,当前线程会进入阻塞状态,释放CPU资源,其他线程可以利用这个时间片执行。sleep()方法不会释放锁或监视器,即如果线程在同步块或方法内调用sleep(),它仍然持有锁。

sleep()方法可以抛出InterruptedException,这意味着如果线程在休眠期间被中断,sleep()会抛出此异常。因此,调用sleep()时通常需要处理这个异常。

1.3 sleep()方法的应用场景

  • 限速操作:当需要控制某些操作的执行频率时,可以使用sleep()方法。例如,在游戏循环中控制帧率,或者在网络请求中限制请求的发送频率。
  • 等待条件:在某些场景下,线程可能需要等待一段时间后再重新检查某个条件,这时可以使用sleep()来实现。
  • 模拟延迟sleep()可以用于模拟任务的执行延迟,以便在测试和调试中更好地模拟真实的执行环境。

1.4 sleep()方法的示例

public class SleepExample {
    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
            System.out.println("Thread is going to sleep...");
            try {
                Thread.sleep(2000);  // 线程休眠2秒
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("Thread is awake!");
        });

        thread.start();
    }
}

在这个示例中,线程在启动后进入休眠状态2秒钟,然后继续执行剩余的代码。

2. yield()方法

2.1 yield()方法的定义

yield()方法是Thread类的另一个静态方法,用于提示线程调度器当前线程愿意让出CPU资源,以便让其他同优先级或更高优先级的线程获得执行机会。yield()方法的调用并不保证当前线程会立刻让出CPU资源,也不保证其他线程会获得执行机会,这完全取决于线程调度器的实现和当前的系统负载。

public static native void yield();

2.2 yield()方法的工作原理

当线程调用Thread.yield()时,线程调度器会检查是否有其他同优先级或更高优先级的线程处于可运行状态(Runnable)。如果有,它们将获得执行机会;如果没有,当前线程可能继续运行。因此,yield()的作用类似于告诉调度器:“我现在已经完成了一些工作,你可以选择让其他线程执行。”

yield()方法不会阻塞线程,线程仅仅是从“运行状态”(Running)进入“可运行状态”(Runnable),以便让其他线程有机会运行。

2.3 yield()方法的应用场景

  • 调试和测试:在调试和测试多线程应用程序时,yield()可以帮助模拟和验证线程调度行为。
  • 减轻竞争:在某些竞争条件较高的场景中,yield()可以用于提示线程调度器切换到其他线程,减轻线程之间的竞争。
  • 协作式多任务处理:虽然现代操作系统多采用抢占式调度,但在某些情况下,yield()可以帮助实现一种类似协作式调度的效果,特别是在多线程计算密集型任务中。

2.4 yield()方法的示例

public class YieldExample {
    public static void main(String[] args) {
        Runnable task1 = () -> {
            for (int i = 0; i < 5; i++) {
                System.out.println("Task 1 - " + i);
                Thread.yield();  // 提示调度器让出CPU
            }
        };

        Runnable task2 = () -> {
            for (int i = 0; i < 5; i++) {
                System.out.println("Task 2 - " + i);
                Thread.yield();  // 提示调度器让出CPU
            }
        };

        Thread thread1 = new Thread(task1);
        Thread thread2 = new Thread(task2);

        thread1.start();
        thread2.start();
    }
}

在这个示例中,两个线程交替运行,每个线程在完成一次循环后调用yield(),提示调度器将CPU时间分配给其他线程。

3. sleep()和 yield()的区别

3.1 目的不同

  • sleep()sleep()的主要目的是使线程进入休眠状态一段时间,从而暂停执行并释放CPU资源。在这段时间内,线程不参与竞争,也不消耗CPU资源,直到休眠时间结束或被中断。

  • yield()yield()的目的是提示线程调度器当前线程愿意让出CPU资源,使其他同优先级或更高优先级的线程有机会执行。yield()并不保证当前线程会被挂起,它只是表明当前线程愿意短暂地让出CPU时间片。

3.2 行为不同

  • sleep()sleep()是明确的时间控制,线程在调用sleep()后会休眠指定的时间。在这段时间内,线程不会执行任何操作,并且该线程必须等待时间结束后才能继续执行。

  • yield()yield()没有时间控制,它只是将当前线程从“运行状态”切换到“可运行状态”。它并不一定会导致线程让出CPU时间片,调度器可能让当前线程继续运行,也可能选择其他线程。

3.3 对线程状态的影响

  • sleep():调用sleep()会使线程进入“阻塞状态”(Blocked),直到指定的时间到达或被中断。

  • yield():调用yield()不会使线程进入阻塞状态,线程仍然处于“可运行状态”(Runnable),只是在等待调度器的重新调度。

3.4 是否释放锁

  • sleep()sleep()不会释放线程持有的任何锁,即使线程在同步块内调用sleep(),锁仍然会被持有,其他线程无法获取该锁。

  • yield()yield()也不会释放锁。线程在调用yield()时仍然持有所有锁,这意味着即使线程短暂让出CPU,其他线程也无法进入该线程所持有的同步块。

3.5 抛出异常的情况

  • sleep()sleep()可能会抛出InterruptedException,如果线程在休眠期间被其他线程中断,必须处理这个异常。

  • yield()yield()不会抛出InterruptedException或任何其他异常。

3.6 实际使用效果

  • sleep():适用于需要明确暂停执行的场景,如限速、等待条件等。sleep()确保线程在指定的时间内不执行任何任务,并让出CPU资源。

  • yield():适用于想要让调度器考虑切换到其他线程执行的场景。yield()的效果取决于线程调度器的实现,不保证一定会切换到其他线程。

4. sleep()和 yield()的应用场景总结

4.1 sleep()的应用场景

  • 实现定时任务:在定时任务中,sleep()可以用来使线程等待指定时间,然后继续执行任务。
  • 限速处理:在网络请求、数据处理等场景中,sleep()可以用来控制执行频率,防止系统过载。
  • 模拟延迟:在测试中,sleep()可以用来模拟任务

的延迟执行,以便验证程序的行为。

4.2 yield()的应用场景

  • 调试和测试yield()可以帮助调试多线程程序,检查线程调度行为,尤其是在竞争条件较高的情况下。
  • 减轻竞争:在高竞争场景中,yield()可以提示调度器切换到其他线程,从而减少资源竞争的激烈程度。
  • 优化并发性能:在某些计算密集型任务中,yield()可以帮助实现更公平的调度,避免某些线程长时间占用CPU。

5. 结束语

sleep()yield()是Java多线程编程中的两个重要方法,尽管它们都可以控制线程的执行顺序和时间,但它们的作用和应用场景有显著的区别。sleep()用于明确的时间控制,让线程进入休眠状态,并让出CPU资源;而yield()用于提示调度器当前线程愿意让出CPU,但不保证会让出。

在实际开发中,合理使用sleep()yield(),可以有效地控制线程的执行顺序,优化并发程序的性能,避免不必要的资源竞争。

到此这篇关于java中线程的sleep()方法和yield()方法的区别的文章就介绍到这了,更多相关java sleep()和yield()内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Spring动态管理定时任务之ThreadPoolTaskScheduler解读

    Spring动态管理定时任务之ThreadPoolTaskScheduler解读

    这篇文章主要介绍了Spring动态管理定时任务之ThreadPoolTaskScheduler解读,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-12-12
  • Java并发编程之对象的组合

    Java并发编程之对象的组合

    这篇文章主要介绍了Java并发编程之对象的组合,文章基于Java的相关资料展开主题内容,具有一定的参考价值,需要的小伙伴可以参考一下
    2022-04-04
  • 浅谈springMVC中controller的几种返回类型

    浅谈springMVC中controller的几种返回类型

    这篇文章主要介绍了浅谈springMVC中controller的几种返回类型,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-02-02
  • Springboot集成Mybatis-Flex的示例详解

    Springboot集成Mybatis-Flex的示例详解

    Mybatis-Flex 是一个优雅的 Mybatis 增强框架,它非常轻量、同时拥有极高的性能与灵活性,本文主要介绍了Springboot集成Mybatis-Flex的示例详解,具有一定的参考价值,感兴趣的可以了解一下
    2024-01-01
  • Springboot3整合Mybatis3的完整步骤记录

    Springboot3整合Mybatis3的完整步骤记录

    这篇文章主要给大家介绍了关于Springboot3整合Mybatis3的完整步骤,Spring Boot和MyBatis分别是两个功能强大的框架,它们的协同使用可以极大地简化数据访问层的开发,提高整体的开发效率,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2024-01-01
  • spring boot+mybatis搭建一个后端restfull服务的实例详解

    spring boot+mybatis搭建一个后端restfull服务的实例详解

    这篇文章主要介绍了spring boot+mybatis搭建一个后端restfull服务,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-11-11
  • 如何设置Spring Boot测试时的日志级别

    如何设置Spring Boot测试时的日志级别

    Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。下面我们来一起学习一下吧
    2019-06-06
  • Java 基础--Arrays工具类详解

    Java 基础--Arrays工具类详解

    这篇文章主要介绍了Java Arrays工具类用法,结合实例形式分析了java Arrays工具类针对数组元素修改、复制、排序等操作使用技巧与相关注意事项,需要的朋友可以参考下
    2021-09-09
  • IDEA生成项目maven-tree依赖目录树结构方式

    IDEA生成项目maven-tree依赖目录树结构方式

    这篇文章主要介绍了IDEA生成项目maven-tree依赖目录树结构方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-12-12
  • java树形菜单对象生成

    java树形菜单对象生成

    这篇文章主要为大家详细介绍了java树形菜单对象生成,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-05-05

最新评论