只有runnable到running时才会占用cpu时间片,其他都会出让cpu时间片。
线程的资源有不少,但应该包含CPU资源和锁资源这两类。
sleep(long mills):让出CPU资源,但是不会释放锁资源。
wait():让出CPU资源和锁资源。

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的方法:

Object参考:Java超类-java.lang.object

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

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

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

sleep与Wait的区别:sleep是线程方法,wait是object方法;看区别,主要是看CPU的运行机制:

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

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

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

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

sleep ,释放cpu资源,不释放锁资源,如果线程进入sleep的话,释放cpu资源,如果外层包有Synchronize,那么此锁并没有释放掉。

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

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

最后:

1.sleep:Thread类的方法,必须带一个时间参数。会让当前线程休眠进入阻塞状态并释放CPU(阿里面试题 Sleep释放CPU,wait 也会释放cpu,因为cpu资源太宝贵了,只有在线程running的时候,才会获取cpu片段),提供其他线程运行的机会且不考虑优先级,但如果有同步锁则sleep不会释放锁即其他线程无法获得同步锁  可通过调用interrupt()方法来唤醒休眠线程。

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则会执行完毕,导致结果不可预测。

关于Java中线程的生命周期,首先看一下下面这张较为经典的图:

上图中基本上囊括了Java中多线程各重要知识点。掌握了上图中的各知识点,Java中的多线程也就基本上掌握了。主要包括:

线程的5个状态

1、新建状态(New):当线程对象对创建后,即进入了新建状态,如:Thread t = new MyThread();

2、就绪状态(Runnable):当调用线程对象的start()方法(t.start();),线程即进入就绪状态。处于就绪状态的线程,只是说明此线程已经做好了准备,随时等待CPU调度执行,获取cpu 的使用权,并不是说执行了t.start()此线程立即就会执行

3、运行状态(Running):可运行状态(runnable)的线程获得了cpu 时间片(timeslice) ,执行程序代码。 当CPU开始调度处于就绪状态的线程时,此时线程才得以真正执行,即进入到运行状态。注:就 绪状态是进入到运行状态的唯一入口,也就是说,线程要想进入运行状态执行,首先必须处于就绪状态中;

4、阻塞状态(Blocked):处于运行状态中的线程由于某种原因,暂时放弃对CPU的使用权,,也即让出了cpu timeslice, 停止执行,此时进入阻塞状态,直到其进入到就绪状态,才 有机会再次被CPU调用以进入到运行状态。才有机会再次获得cpu timeslice 转到运行(running)状态 根据阻塞产生的原因不同,阻塞状态又可以分为三种:

1.等待阻塞:运行状态中的线程执行wait()方法,使本线程进入到等待阻塞状态;,JVM会把该线程放入等待队列(waitting queue)中。

2.同步阻塞 –,运行(running)的线程在获取对象的同步锁时,若该同步锁被别的线程占用,获取synchronized同步锁失败 , 它会进入同步阻塞状态 ,则JVM会把该线程放入锁池(lock pool)中。

3.其他阻塞 – 通过调用线程的sleep()或join()或发出了I/O请求时,线程会进入到阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。运行(running)的线程执行Thread.sleep(long ms)或t.join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入可运行(runnable)状态。

5、死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。

从图中可以看出,只有runnable到running时才会占用cpu时间片,其他都会出让cpu时间片。
线程的资源有不少,但应该包含CPU资源和锁资源这两类。
sleep(long mills):让出CPU资源,但是不会释放锁资源。
wait():让出CPU资源和锁资源。
锁是用来线程同步的,sleep(long mills)虽然让出了CPU,但是不会让出锁,其他线程可以利用CPU时间片了,但如果其他线程要获取sleep(long mills)拥有的锁才能执行,则会因为无法获取锁而不能执行,继续等待。
但是那些没有和sleep(long mills)竞争锁的线程,一旦得到CPU时间片即可运行了。

5. 死亡(DEAD):线程run()、main() 方法执行结束,或者因异常退出了run()方法,则该线程结束生命周期。死亡的线程不可再次复生。

我写了个例子:

public class abc_test {

    public static void main(String[] args) {
// TODO Auto-generated method stub Thread thread =new Thread(new joinDemo());
thread.start(); for(int i=0;i<20;i++){ System.out.println("主线程第"+i+"此执行!"); if(i>=2){ try{
//t1线程合并到主线程中,主线程停止执行过程,转而执行t1线程,直到t1执行完毕后继续;
thread.join();
}catch(InterruptedException e){
e.printStackTrace();
}
}
} } } class joinDemo implements Runnable{ @Override
public void run() {
// TODO Auto-generated method stub for(int i=0;i<10;i++){ System.out.println("线程1第"+i+"次执行");
} } }

结果为:

主线程第0此执行!
主线程第1此执行!
主线程第2此执行!
线程1第0次执行
线程1第1次执行
线程1第2次执行
线程1第3次执行
线程1第4次执行
线程1第5次执行
线程1第6次执行
线程1第7次执行
线程1第8次执行
线程1第9次执行
主线程第3此执行!
主线程第4此执行!
主线程第5此执行!
主线程第6此执行!
.....
主线程第19此执行!

也可参考我专门写的关于线程状态的文章:Java线程的5种状态及切换(透彻讲解)-京东面试

参考:主题:sleep,wait,join,yield有何差别?

参考:java之yield(),sleep(),wait()区别详解-备忘笔记

参考:sleep、yield、wait、join的区别

参考:sleep,yield,join,notify,wait,notifyAll区别

参考:线程sleep和对象wait一段时间的区别

参考:Java线程中sleep()、wait()和notify()和notifyAll()、yield()、join()等方法的用法和区别

参考:理解线程状态,答疑wait与sleep是否占用cpu资源的问题,再来个小demo

sleep、yield、wait、join的区别(阿里面试)的更多相关文章

  1. sleep、yield、wait、join的区别(阿里)

    只有runnable到running时才会占用cpu时间片,其他都会出让cpu时间片.线程的资源有不少,但应该包含CPU资源和锁资源这两类.sleep(long mills):让出CPU资源,但是不会 ...

  2. java多线程中 volatile与synchronized的区别-阿里面试

    volatile 与 synchronized 的比较(阿里面试官问的问题) ①volatile轻量级,只能修饰变量.synchronized重量级,还可修饰方法 ②volatile只能保证数据的可见 ...

  3. HTTP协议 结构,get post 区别(阿里面试)

    如果需要想了解相关的TCP的协议结构,底层架构,以及每次面试必问的三次握手,四次挥手可以 参考:TCP协议详解7层和4层解析(美团面试,阿里面试) 尤其是三次握手,四次挥手 具体发送的报文和状态都要掌 ...

  4. Java Thread类的yield()和join()的区别和用法

    yield: 解释它之前,先简述下,多线程的执行流程:多个线程并发请求执行时,由cpu决定优先执行哪一个,即使通过thread.setPriority(),设置了 线程的优先级,也不一定就是每次都先执 ...

  5. BeanFactory 简介以及它 和FactoryBean的区别(阿里面试)

    BeanFacotry是spring中比较原始的Factory.如XMLBeanFactory就是一种典型的BeanFactory.原始的BeanFactory无法支持spring的许多插件,如AOP ...

  6. 多线程的sleep、yield、join用法及sleep与wait的区别

    Thread类的方法列表:sleep.yield.join用于线程的协作,围绕线程的调度 1.join()等待线程结束:调用join方法的线程,执行结束后才会释放锁.主线程main中调用启动线程(调用 ...

  7. sleep、yield、join方法简介与用法 sleep与wait区别 多线程中篇(十五)

    Object中的wait.notify.notifyAll,可以用于线程间的通信,核心原理为借助于监视器的入口集与等待集逻辑 通过这三个方法完成线程在指定锁(监视器)上的等待与唤醒,这三个方法是以锁( ...

  8. 你能说出多线程中sleep、yield、join的用法及sleep与wait区别?

    Object中的wait.notify.notifyAll,可以用于线程间的通信,核心原理为借助于监视器的入口集与等待集逻辑 通过这三个方法完成线程在指定锁(监视器)上的等待与唤醒,这三个方法是以锁( ...

  9. Java程序员从阿里面试回来,这些面试题你们会吗?

    前不久刚从阿里面试回来,为了这场面试可以说准备了一个半月,做的准备就是刷题和看视频看书充实自己的技术,话说是真难啊,不过还算顺利拿到了offer,有很多面试题我已经记不起来了,这些是当天回家整理好的, ...

随机推荐

  1. 使用RMAN Active duplicate创建异地auxiliary Database

    1g的RMAN duplicate 可以通过Active database duplicate和Backup-based duplicate两种方法实现.这里的测试使用的是Active databas ...

  2. P3512 [POI2010]PIL-Pilots-洛谷luogu

    刚研究完单调队列和单调栈 于是就找题做了 发现了这道蓝题 以为很简单 就着手来写了 然而 并不是我想的那样 只是有一点点思路 无奈 还是看了题解 好吧题解是真的挺好的 ---------------- ...

  3. Python基础(2)——列表、字典、数据运算

    1.列表 #创建列表 name_list = ['alex', 'seven', 'eric'] #或 name_list = list(['alex', 'seven', 'eric']) #访问列 ...

  4. ES6中Object.assign() 方法

    ES6中Object.assign() 方法 1. 对象合并Object.assign 方法用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象上.如下代码演示: var targ ...

  5. <<linux device driver,third edition>> Chapter 3:Char Drivers

    The Internal Representation of Device Numbers Within the kernel,the dev_t type(defined in linux/type ...

  6. Python脱产8期 Day01

    一 编程语言与目的 1.有特定语法,可以通过编程的方式,让计算机进行识别,从而让计算机根据人的意愿完成人想让其完成的事 2.控制奴役计算机,让其完成你想让它完成的事,从而解放人力. 二 计算机 五大组 ...

  7. centos 6 中恢复删除的文件

    CentOS 6 安裝 extundelete:: ##############测试的时候需要2块硬盘############### yum install e2fsprogs-devel e2fsp ...

  8. VSCode Install Go

    首先是VScode官网下载:https://code.visualstudio.com/ 然后在电脑上安装go的环境 如下图在VSCode上搜go的插件进行安装: 推荐:vscode-icons这个插 ...

  9. POJ3301 Texas Trip 计算几何、随机化贪心

    传送门--Vjudge 三分写法似乎有问题,可以去Udebug上看Morass的\(666\)个测试点的数据,我的乱搞有很多比正解答案小,但还是能在SPOJ和POJ过,可见数据之水. 可以对正方形的角 ...

  10. 把cnblogs变成简书 - cnblogs博客自定义皮肤css样式

    吐槽 博客园cnblogs作为老牌的IT技术博客类网站,为广大的开发者提供了非常不错的学习交流平台. 虽然博客内容才是重点,但是如果有赏心悦目的页面不更好吗! cnblogs可以更换博客模板,并且提供 ...