sleep、yield、wait、join的区别简述

总体归纳:

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

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

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

Object 是java.lang.Object,由于每天说Java是面向对象的,因此Object是全部Java对象的超类,都实现Object的方法;dom

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

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

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

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

sleep与Wait的区别:

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

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

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

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

明白了以上两点的含义,开始分析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次

参考地址:

http://www.javashuo.com/article/p-zrjvozwb-hp.html

http://www.javashuo.com/article/p-xvjmresi-bw.html

相关文章
相关标签/搜索