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
看区别,主要是看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则会执行完毕,致使结果不可预测。
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次
参考地址: