如何理解Java中的Wait和Sleep?

29 篇文章 0 订阅
本文介绍了Java中sleep()和wait()方法的基本概念、使用场景和区别,强调了它们在控制线程执行和同步中的作用,并讨论了wait可能导致的死锁问题。此外,文章还推荐了使用ScheduledExecutorService进行定时任务的实践和注意事项。
摘要由CSDN通过智能技术生成

本文主要介绍Java中关于线程同步的一些基本概念和方法,包括sleep()和wait()的用法和区别。

首先,Java中的wait和sleep都是用来控制线程的执行的方法,但是它们的使用场景和底层实现有很大的区别。

sleep

sleep的作用是让线程休眠指定时间,然后重新进入就绪状态。sleep可以在任何地方使用,不需要获取锁。sleep的使用场景主要是控制线程执行的时间,比如实现定时任务。

public static void sleep(long millis) throws InterruptedException {
    Thread.sleep(millis);
}

wait

wait的作用是让线程等待,直到其他线程调用notify或notifyAll方法,使该线程重新进入就绪状态,唤醒它,或者等待时间结束。wait通常和synchronized关键字一起使用,用于线程间的协调和通信。wait必须在synchronized块中调用,否则会抛出IllegalMonitorStateException异常。wait的使用场景主要是在线程间进行通信,等待某个条件的满足。

public static void wait(long millis) throws InterruptedException {
    Thread.sleep(millis);
    synchronized (this) {
        while (!isDone) {
            wait(0);
        }
    }
}

区别

两个方法的区别在于,sleep()方法会释放线程的锁,而wait()方法不会。因此,当一个线程想要等待另一个线程完成某个操作时,应该使用wait()方法,而当一个线程想要暂停一段时间时,应该使用sleep()方法。

存在的问题

wait和sleep方法都存在一些问题:

  • wait方法容易造成死锁。如果一个线程在等待另一个线程唤醒它,而另一个线程正好在等待它释放锁,就会出现死锁。
  • sleep方法不能保证精确的休眠时间,因为线程进入休眠状态后,可能会被其他线程唤醒或者中断。
  • wait和sleep方法都会使线程进入阻塞状态,如果不恰当地使用,容易导致线程饥饿、死锁等问题。

至于如何高效地使用阻塞, 更多可以参考下方的拓展阅读,比如说使用TimeUnit.SECONDS.sleep("你的暂停时间");

或者利用组件ScheduledExecutorService来实现定时操作。

ScheduledExecutorService

ScheduledExecutorService是Java中的一个线程池,用于执行定时任务或周期性任务。它继承了ExecutorService接口,可以使用submit()方法提交任务,并使用get()方法获取任务的Future对象,以便获取任务的执行结果。

我们以代码实例进行说明,比方说我们要实现一个轮询操作

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class ScheduledExecutorServiceExample {

    public static void main(String[] args) {
        ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1);

        Runnable task = new Runnable() {
            @Override
            public void run() {
                System.out.println("Task executed");
            }
        };

        executorService.scheduleAtFixedRate(task, 5, 10, TimeUnit.SECONDS);
    }
}

上述代码创建了一个ScheduledExecutorService对象,并使用scheduleAtFixedRate()方法提交了一个定时任务。该任务每隔10秒钟执行一次,一共执行5次。

在任务执行时,我们打印了一条消息,表示任务已经被执行。 需要注意的是,ScheduledExecutorService中的任务是线程安全的,因此可以在多个线程之间共享同一个ScheduledExecutorService对象。此外,ScheduledExecutorService还支持延迟时间和周期执行任务的方式,可以根据实际需求选择合适的方式来提交任务。

另外,虽然这个Service可以实现多线程共享,但是在线程较多时难免会产生竞态条件,此时我们可以为每个线程创建一个独立的Service对象。


参考资料

Java并发常见面试题总结(上) | JavaGuide(Java面试 + 学习指南)

wait - How do I make a delay in Java? - Stack Overflow

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值