Java线程Thread.yeild方法解析

Java线程Thread的yeild方法可能在日常使用中比较少出现,那它是做什么用的,我们先查查官方文档解释。

yield
public static void yield()
Causes the currently executing thread object to temporarily pause and allow other threads to execute.

看原版官方文档可以避免出现歧义,我的理解是

造成当前正在执行的线程对象临时性的暂停,和允许其他线程去执行

也就是说,调用了yield方法之后,当前线程会临时性的暂停一下,然后其他线程有机会去执行任务。那么实际情况是怎么样,我们用例子来测试一下。

public class YieldTest{

  private static final int DEST_NUM = 50;

  public static void main(String[] args) {
    new YieldTest();
  }

  public YieldTest(){

    ThreadDemo yt1 = new ThreadDemo("张三");
    ThreadDemo yt2 = new ThreadDemo("李四");
    ThreadDemo yt3 = new ThreadDemo("王五");

    //yt1.setPriority(10);
    //yt1.setPriority(5);
    //yt3.setPriority(1);

    yt1.start();
    yt2.start();
    yt3.start();

  }

  public class ThreadDemo extends Thread{

    public ThreadDemo(String name){
      setName(name);
    }

    @Override public void run() {

      for (int i = 1; i <= DEST_NUM; i++) {

        // 当i为30时,该线程就会把CPU时间让掉,让其他或者自己的线程执行(也就是谁先抢到谁执行)
        if (i % 5 == 0) {
          System.out.println("" + this.getName() + "-----" + i + "    yeild一下");
          yield();
        }else{
          System.out.println("" + this.getName() + "-----" + i);
        }
      }

    }

  }

}

上面的例子是,开启张三,李四,王五三个线程分别打印从1到50的数字,每当打印的数字是5的倍数时(比如打印5,10,15等),就yield一下。那么我们看看运行之后的结果是怎么样的。

张三-----1
王五-----1
李四-----1
王五-----2
王五-----3
王五-----4
张三-----2
张三-----3
王五-----5    yeild一下
李四-----2
李四-----3
李四-----4
李四-----5    yeild一下      /////////
李四-----6
李四-----7
李四-----8
王五-----6
王五-----7
王五-----8
王五-----9
王五-----10    yeild一下
张三-----4
张三-----5    yeild一下     //////////
张三-----6
张三-----7
张三-----8
张三-----9
张三-----10    yeild一下    /////////
张三-----11
张三-----12
张三-----13
张三-----14
张三-----15    yeild一下    /////////
张三-----16
张三-----17
张三-----18
张三-----19

//其余的省略
。。。

可以看到这次张三虽然多次yeild了,但是依然继续执行了。我们再运行一次看看

张三-----1
张三-----2
张三-----3
张三-----4
张三-----5    yeild一下
李四-----1
李四-----2
李四-----3
李四-----4
李四-----5    yeild一下
王五-----1
王五-----2
王五-----3
王五-----4
王五-----5    yeild一下
张三-----6
张三-----7
张三-----8
张三-----9
张三-----10    yeild一下
李四-----6
李四-----7
李四-----8
李四-----9
李四-----10    yeild一下
王五-----6
王五-----7
王五-----8
王五-----9
王五-----10    yeild一下
张三-----11
张三-----12
张三-----13
张三-----14
张三-----15    yeild一下
李四-----11
李四-----12
李四-----13
李四-----14
李四-----15    yeild一下
王五-----11
王五-----12
王五-----13
王五-----14
王五-----15    yeild一下
张三-----16
张三-----17
张三-----18
张三-----19
张三-----20    yeild一下
李四-----16
李四-----17

//其余的省略
。。。

yield原理

发现这一次,每次调用了yeild之后,它们都没有紧接着执行了。这是为什么呢,难道yield没有用处了吗?
其实上面出现的不确定结果,是因为多核CPU执行的关系,一个线程调用了yield方法之后,确实会让出当前使用的CPU,让自己从【运行态】变为【就绪态】。

  • 当运行环境是单核CPU的时候。如果其他线程已经处于就绪态,正在等待CPU时间片时,这时有线程yield让出了CPU时间片,它们中的一个就会先有可能分配到CPU时间片,进而进入【运行态】,执行线程内容。
  • 而当运行环境是多核CPU的话。也许上面的三个线程都是同时处于【运行态】正在执行,那个一个线程yiedl之后,短暂的让出了它的CPU,而此时又没有线程跟它抢CPU(因为其他两个都在运行着),所以它可能又获得了CPU时间片又去执行了。所以针对多核CPU环境的话,测试结果并没有明显的规律。

yield错误观点纠正

网上有说“yield之后,只有同优先级的线程能执行,低优先级的线程无法获得执行”,这是错误的观点,Java文档并没有这种说,Java虚拟机也并没有这种限制。会大概率出现这种情况主要是因为yield之后,高优先级的线程会更容易得到调度优先得到CPU时间片执行,低优先级自然被执行的概率就更少了,但是并不是说低优先级线程就无法被执行。可以把上面代码的优先级设置部分注释去掉,自己亲自运行看看结果,别被误导了。

yield的使用场景

yield的作用就是暂时让出使用着的CPU,这样其他【就绪态】的线程就有机会占用这个CPU去执行。所以yield的使用场景多在,当前线程在进行耗时性的操作时(如IO操作),并且因为它的优先级较高,导致一些优先级较低的线程被分配的时间片更少,这样优先级低的线程就要等待更长时间才能完成操作,那么这时适当地调用几次yield方法让出CPU,让优先级低的线程多得到执行,这样才能高效的实现程序执行和响应。

测试例子查看 我的GitHub--JavaTest

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,948评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,371评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,490评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,521评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,627评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,842评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,997评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,741评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,203评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,534评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,673评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,339评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,955评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,770评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,000评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,394评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,562评论 2 349

推荐阅读更多精彩内容

  • 写在前面的话: 这篇博客是我从这里“转载”的,为什么转载两个字加“”呢?因为这绝不是简单的复制粘贴,我花了五六个小...
    SmartSean阅读 4,717评论 12 45
  • 该文章转自:http://blog.csdn.net/evankaka/article/details/44153...
    加来依蓝阅读 7,337评论 3 87
  • Java多线程学习 [-] 一扩展javalangThread类 二实现javalangRunnable接口 三T...
    影驰阅读 2,952评论 1 18
  • 本文主要讲了java中多线程的使用方法、线程同步、线程数据传递、线程状态及相应的一些线程函数用法、概述等。 首先讲...
    李欣阳阅读 2,444评论 1 15
  • 不知不觉,我已经是一名大三的学生,经历过小考,中考,高考,过五关斩六将,不知不觉已经开始面临着考研或者是毕...
    玄德帝阅读 364评论 0 2