温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

java中sleep、yield、wait、join的区别是什么

发布时间:2021-07-06 11:57:35 来源:亿速云 阅读:237 作者:chen 栏目:大数据

这篇文章主要讲解了“java中sleep、yield、wait、join的区别是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“java中sleep、yield、wait、join的区别是什么”吧!

整体概括:

1.  Thread.sleep(long) 和Thread.yield()都是Thread类的静态方法,在调用的时候都是Thread.sleep(long)/Thread.yield()的方式进行调用。

   而join()是由线程对象来调用。

2.wait()和notify()、notifyAll()  这三个方法都是java.lang.Object的方法! 

Object 是java.lang.Object,因为天天说Java是面向对象的,所以Object是所有Java对象的超类,都实现Object的方法;

它们都是用于协调多个线程对共享数据的存取,所以必须在Synchronized语句块内使用这三个方法。前面说过Synchronized这个关键字用于保护共享数据,阻止其他线程对共享数据的存取。但是这样程序的流程就很不灵活了,如何才能在当前线程还没退出Synchronized数据块时让其他线程也有机会访问共享数据呢?此时就用这三个方法来灵活控制。 

wait()方法使当前线程暂停执行并释放对象锁标志,让其他线程可以进入Synchronized数据块,当前线程被放入对象等待池中。

当调用 notify()方法后,将从对象的等待池中移走一个任意的线程并放到锁标志等待池中,只有锁标志等待池中的线程能够获取锁标志;如果锁标志等待池中没有线程,则notify()不起作用。 

notifyAll()则从对象等待池中移走所有等待那个对象的线程并放到锁标志等待池中。 

sleep与Wait的区别:

看区别,主要是看CPU的运行机制:

它们的区别主要考虑两点:1.cpu是否继续执行、2.锁是否释放掉。

对于这两点,首先解释下cpu是否继续执行的含义:cpu为每个线程划分时间片去执行,每个时间片时间都很短,cpu不停地切换不同的线程,以看似他们好像同时执行的效果。

其次解释下锁是否释放的含义:锁如果被占用,那么这个执行代码片段是同步执行的,如果锁释放掉,就允许其它的线程继续执行此代码块了。 

明白了以上两点的含义,开始分析sleep和wait:

sleep一段时间之后,往往线程会立即执行,可见cpu一直在为此线程分配时间片,如果外层包有Synchronize,那么此锁并没有释放掉。因此sleep cpu继续执行、锁并没有释放掉;

wait,一般用于锁机制中

(wait用于锁机制,sleep不是,这就是为啥sleep不释放锁,wait释放锁的原因,sleep是线程的方法,跟锁没半毛钱关系,wait,notify,notifyall是一起使用的,用于锁机制),

肯定是要释放掉锁的,因为notify并不会立即调起此线程,因此cpu是不会为其分配时间片的,也就是说wait 线程进入等待池,cpu不分时间片给它,锁释放掉。

说明:

1.sleep:Thread类的方法,必须带一个时间参数。会让当前线程休眠进入阻塞状态并释放CPU(阿里面试题 Sleep释放CPU,wait呢),提供其他线程运行的机会且不考虑优先级,但如果有同步锁则sleep不会释放锁即其他线程无法获得同步锁

2.yield:让出CPU调度,Thread类的方法,类似sleep只是不能由用户指定暂停多长时间 ,并且yield()方法只能让同优先级的线程有执行的机会。 yield()只是使当前线程重新回到可执行状态,所以执行yield()的线程有可能在进入到可执行状态后马上又被执行。调用yield方法只是一个建议,告诉线程调度器我的工作已经做的差不多了,可以让别的相同优先级的线程使用CPU了,没有任何机制保证采纳。

3.wait:Object类的方法(notify()、notifyAll()  也是Object对象),必须放在循环体和同步代码块中,执行该方法的线程会释放锁,进入线程等待池中等待被再次唤醒(notify随机唤醒,notifyAll全部唤醒,线程结束自动唤醒)即放入锁池中竞争同步锁

4.join:一种特殊的wait,当前运行线程调用另一个线程的join方法,当前线程进入阻塞状态直到另一个线程运行结束等待该线程终止。 注意该方法也需要捕捉异常。

等待调用join方法的线程结束,再继续执行。如:t.join();//主要用于等待t线程运行结束,若无此句,main则会执行完毕,导致结果不可预测。

几个方法的比较

  1. Thread.sleep(long millis),一定是当前线程调用此方法,当前线程进入阻塞,但不释放对象锁,millis后线程自动苏醒进入可运行状态。作用:给其它线程执行机会的最佳方式。

  2. Thread.yield(),一定是当前线程调用此方法,当前线程放弃获取的cpu时间片,由运行状态变会可运行状态,让OS再次选择线程。作用:让相同优先级的线程轮流执行,但并不保证一定会轮流执行。实际中无法保证yield()达到让步目的,因为让步的线程还有可能被线程调度程序再次选中。Thread.yield()不会导致阻塞。

  3. t.join()/t.join(long millis),当前线程里调用其它线程1的join方法,当前线程阻塞,但不释放对象锁,直到线程1执行完毕或者millis时间到,当前线程进入可运行状态。

  4. obj.wait(),当前线程调用对象的wait()方法,当前线程释放对象锁,进入等待队列。依靠notify()/notifyAll()唤醒或者wait(long timeout)timeout时间到自动唤醒。

  5. obj.notify()唤醒在此对象监视器上等待的单个线程,选择是任意性的。notifyAll()唤醒在此对象监视器上等待的所有线程。

show codes time

import lombok.extern.slf4j.Slf4j;

import java.util.Random;

/**
 * 实现线上
 * @author wucj
 * @date 2019-06-30 16:40
 **/
@Slf4j
public class ThreadAStatus implements Runnable{

    private String name;

    private volatile int count;

    public ThreadAStatus(String name){
        this.name = name;
    }

    @Override
    public void run() {
        log.info("线程{},执行次数:{}",name,++count);
        try{
            log.info("线程{}开始执行,当前第:{}次",name,count);
            int maxCount = 10;
            for(int i=0;i<maxCount;i++){
                log.info("线程{}开始执行,当前第:{}次",name,++count);
                int thisSleepSeconds = new Random().nextInt(5);
                log.info("线程:{},睡眠:{}秒",name,thisSleepSeconds);
            }
        }catch (Exception e){
            log.error("线程:{}异常:{}",name,e);
        }
    }
}


import com.cjw.concurrent.thd.ThreadAStatus;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;

/**
 * @author wucj
 * @date 2019-06-30 16:47
 **/
@Slf4j
public class ThreadStatusTest {

    @Test
    public void threadStatusAB(){
        ThreadAStatus threadAStatus = new ThreadAStatus("A");
        ThreadAStatus threadBStatus = new ThreadAStatus("B");
        Thread threadA = new Thread(threadAStatus);
        Thread threadB = new Thread(threadBStatus);
        threadA.start();
        threadB.start();
        try{
            for(int i=0;i<10;i++){
                log.info("当前为:{},执行第:{}次",Thread.currentThread().getName(),i);
                threadA.join();
                threadB.join();
            }
            Thread.sleep(100*1000);
        }catch (Exception e){
            log.error("thread.join异常{}",e);
        }

    }

}

Connected to the target VM, address: '127.0.0.1:64837', transport: 'socket'
17:25:06.227 [main] INFO com.cjw.concurrent.ThreadStatusTest - 当前为:main,执行第:0次
17:25:06.227 [Thread-1] INFO com.cjw.concurrent.thd.ThreadAStatus - 线程B,执行次数:1
17:25:06.227 [Thread-0] INFO com.cjw.concurrent.thd.ThreadAStatus - 线程A,执行次数:1
17:25:06.248 [Thread-0] INFO com.cjw.concurrent.thd.ThreadAStatus - 线程A开始执行,当前第:1次
17:25:06.247 [Thread-1] INFO com.cjw.concurrent.thd.ThreadAStatus - 线程B开始执行,当前第:1次
17:25:06.248 [Thread-0] INFO com.cjw.concurrent.thd.ThreadAStatus - 线程A开始执行,当前第:2次
17:25:06.248 [Thread-1] INFO com.cjw.concurrent.thd.ThreadAStatus - 线程B开始执行,当前第:2次
17:25:06.251 [Thread-1] INFO com.cjw.concurrent.thd.ThreadAStatus - 线程:B,睡眠:4秒
17:25:06.251 [Thread-0] INFO com.cjw.concurrent.thd.ThreadAStatus - 线程:A,睡眠:3秒
17:25:06.251 [Thread-1] INFO com.cjw.concurrent.thd.ThreadAStatus - 线程B开始执行,当前第:3次
17:25:06.251 [Thread-0] INFO com.cjw.concurrent.thd.ThreadAStatus - 线程A开始执行,当前第:3次
17:25:06.251 [Thread-1] INFO com.cjw.concurrent.thd.ThreadAStatus - 线程:B,睡眠:4秒
17:25:06.251 [Thread-0] INFO com.cjw.concurrent.thd.ThreadAStatus - 线程:A,睡眠:2秒
17:25:06.251 [Thread-1] INFO com.cjw.concurrent.thd.ThreadAStatus - 线程B开始执行,当前第:4次
17:25:06.251 [Thread-0] INFO com.cjw.concurrent.thd.ThreadAStatus - 线程A开始执行,当前第:4次
17:25:06.251 [Thread-0] INFO com.cjw.concurrent.thd.ThreadAStatus - 线程:A,睡眠:1秒
17:25:06.251 [Thread-1] INFO com.cjw.concurrent.thd.ThreadAStatus - 线程:B,睡眠:2秒
17:25:06.251 [Thread-0] INFO com.cjw.concurrent.thd.ThreadAStatus - 线程A开始执行,当前第:5次
17:25:06.251 [Thread-1] INFO com.cjw.concurrent.thd.ThreadAStatus - 线程B开始执行,当前第:5次
17:25:06.251 [Thread-1] INFO com.cjw.concurrent.thd.ThreadAStatus - 线程:B,睡眠:4秒
17:25:06.251 [Thread-1] INFO com.cjw.concurrent.thd.ThreadAStatus - 线程B开始执行,当前第:6次
17:25:06.251 [Thread-1] INFO com.cjw.concurrent.thd.ThreadAStatus - 线程:B,睡眠:4秒
17:25:06.251 [Thread-1] INFO com.cjw.concurrent.thd.ThreadAStatus - 线程B开始执行,当前第:7次
17:25:06.251 [Thread-1] INFO com.cjw.concurrent.thd.ThreadAStatus - 线程:B,睡眠:1秒
17:25:06.251 [Thread-1] INFO com.cjw.concurrent.thd.ThreadAStatus - 线程B开始执行,当前第:8次
17:25:06.251 [Thread-1] INFO com.cjw.concurrent.thd.ThreadAStatus - 线程:B,睡眠:3秒
17:25:06.251 [Thread-1] INFO com.cjw.concurrent.thd.ThreadAStatus - 线程B开始执行,当前第:9次
17:25:06.252 [Thread-1] INFO com.cjw.concurrent.thd.ThreadAStatus - 线程:B,睡眠:3秒
17:25:06.252 [Thread-1] INFO com.cjw.concurrent.thd.ThreadAStatus - 线程B开始执行,当前第:10次
17:25:06.252 [Thread-1] INFO com.cjw.concurrent.thd.ThreadAStatus - 线程:B,睡眠:2秒
17:25:06.252 [Thread-1] INFO com.cjw.concurrent.thd.ThreadAStatus - 线程B开始执行,当前第:11次
17:25:06.252 [Thread-1] INFO com.cjw.concurrent.thd.ThreadAStatus - 线程:B,睡眠:2秒
17:25:06.256 [Thread-0] INFO com.cjw.concurrent.thd.ThreadAStatus - 线程:A,睡眠:3秒
17:25:06.256 [Thread-0] INFO com.cjw.concurrent.thd.ThreadAStatus - 线程A开始执行,当前第:6次
17:25:06.256 [Thread-0] INFO com.cjw.concurrent.thd.ThreadAStatus - 线程:A,睡眠:0秒
17:25:06.256 [Thread-0] INFO com.cjw.concurrent.thd.ThreadAStatus - 线程A开始执行,当前第:7次
17:25:06.256 [Thread-0] INFO com.cjw.concurrent.thd.ThreadAStatus - 线程:A,睡眠:1秒
17:25:06.257 [Thread-0] INFO com.cjw.concurrent.thd.ThreadAStatus - 线程A开始执行,当前第:8次
17:25:06.257 [Thread-0] INFO com.cjw.concurrent.thd.ThreadAStatus - 线程:A,睡眠:2秒
17:25:06.257 [Thread-0] INFO com.cjw.concurrent.thd.ThreadAStatus - 线程A开始执行,当前第:9次
17:25:06.257 [Thread-0] INFO com.cjw.concurrent.thd.ThreadAStatus - 线程:A,睡眠:1秒
17:25:06.257 [Thread-0] INFO com.cjw.concurrent.thd.ThreadAStatus - 线程A开始执行,当前第:10次
17:25:06.257 [Thread-0] INFO com.cjw.concurrent.thd.ThreadAStatus - 线程:A,睡眠:1秒
17:25:06.257 [Thread-0] INFO com.cjw.concurrent.thd.ThreadAStatus - 线程A开始执行,当前第:11次
17:25:06.257 [Thread-0] INFO com.cjw.concurrent.thd.ThreadAStatus - 线程:A,睡眠:1秒
17:25:06.257 [main] INFO com.cjw.concurrent.ThreadStatusTest - 当前为:main,执行第:1次
17:25:06.257 [main] INFO com.cjw.concurrent.ThreadStatusTest - 当前为:main,执行第:2次
17:25:06.257 [main] INFO com.cjw.concurrent.ThreadStatusTest - 当前为:main,执行第:3次
17:25:06.257 [main] INFO com.cjw.concurrent.ThreadStatusTest - 当前为:main,执行第:4次
17:25:06.257 [main] INFO com.cjw.concurrent.ThreadStatusTest - 当前为:main,执行第:5次
17:25:06.257 [main] INFO com.cjw.concurrent.ThreadStatusTest - 当前为:main,执行第:6次
17:25:06.257 [main] INFO com.cjw.concurrent.ThreadStatusTest - 当前为:main,执行第:7次
17:25:06.257 [main] INFO com.cjw.concurrent.ThreadStatusTest - 当前为:main,执行第:8次
17:25:06.257 [main] INFO com.cjw.concurrent.ThreadStatusTest - 当前为:main,执行第:9次

参考地址:

https://www.cnblogs.com/aspirant/p/8900276.html

https://www.cnblogs.com/aspirant/p/8876670.html

感谢各位的阅读,以上就是“java中sleep、yield、wait、join的区别是什么”的内容了,经过本文的学习后,相信大家对java中sleep、yield、wait、join的区别是什么这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是亿速云,小编将为大家推送更多相关知识点的文章,欢迎关注!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI