关闭 x
IT技术网
    技 采 号
    ITJS.cn - 技术改变世界
    • 实用工具
    • 菜鸟教程
    IT采购网 中国存储网 科技号 CIO智库

    IT技术网

    IT采购网
    • 首页
    • 行业资讯
    • 系统运维
      • 操作系统
        • Windows
        • Linux
        • Mac OS
      • 数据库
        • MySQL
        • Oracle
        • SQL Server
      • 网站建设
    • 人工智能
    • 半导体芯片
    • 笔记本电脑
    • 智能手机
    • 智能汽车
    • 编程语言
    IT技术网 - ITJS.CN
    首页 » JAVA »Java线程中yield与join方法的区别

    Java线程中yield与join方法的区别

    2015-02-11 00:00:00 出处:禅楼望月
    分享

    长期以来,多线程问题颇为受到面试官的青睐。虽然我个人认为我们当中很少有人能真正获得机会开发复杂的多线程应用(在过去的七年中,我得到了一个机会),但是理解多线程对增加你的信心很有用。之前,我讨论了一个wait()和sleep()方法区别的问题,这一次,我将会讨论join()和yield()方法的区别。坦白的说,实际上我并没有用过其中任何一个方法,所以,如果你感觉有不恰当的地方,请提出讨论。

    Java线程调度的一点背景

    在各种各样的线程中,Java虚拟机必须实现一个有优先权的、基于优先级的调度程序。这意味着Java程序中的每一个线程被分配到一定的优先权,使用定义好的范围内的一个正整数表示。优先级可以被开发者改变。即使线程已经运行了一定时间,Java虚拟机也不会改变其优先级

    优先级的值很重要,因为Java虚拟机和下层的操作系统之间的约定是操作系统必须选择有最高优先权的Java线程运行。所以我们说Java实现了一个基于优先权的调度程序。该调度程序使用一种有优先权的方式实现,这意味着当一个有更高优先权的线程到来时,无论低优先级的线程是否在运行,都会中断(抢占)它。这个约定对于操作系统来说并不总是这样,这意味着操作系统有时可能会选择运行一个更低优先级的线程。(我憎恨多线程的这一点,因为这不能保证任何事情)

    注意Java并不限定线程是以时间片运行,但是大多数操作系统却有这样的要求。在术语中经常引起混淆:抢占经常与时间片混淆。事实上,抢占意味着只有拥有高优先级的线程可以优先于低优先级的线程执行,但是当线程拥有相同优先级的时候,他们不能相互抢占。它们通常受时间片管制,但这并不是Java的要求。

    理解线程的优先权

    接下来,理解线程优先级是多线程学习很重要的一步,尤其是了解yield()函数的工作过程。

    记住当线程的优先级没有指定时,所有线程都携带普通优先级。 优先级可以用从1到10的范围指定。10表示最高优先级,1表示最低优先级,5是普通优先级。 记住优先级最高的线程在执行时被给予优先。但是不能保证线程在启动时就进入运行状态。 与在线程池中等待运行机会的线程相比,当前正在运行的线程可能总是拥有更高的优先级。 由调度程序决定哪一个线程被执行。 t.setPriority()用来设定线程的优先级。 记住在线程开始方法被调用之前,线程的优先级应该被设定。 你可以使用常量,如MIN_PRIORITY,MAX_PRIORITY,NORM_PRIORITY来设定优先级

    现在,当我们对线程调度和线程优先级有一定理解后,让我们进入主题。

    yield()方法

    理论上,yield意味着放手,放弃,投降。一个调用yield()方法的线程告诉虚拟机它乐意让其他线程占用自己的位置。这表明该线程没有在做一些紧急的事情。注意,这仅是一个暗示,并不能保证不会产生任何影响。

    在Thread.java中yield()定义如下:

    /**
      * A hint to the scheduler that the current thread is willing to yield its current use of a processor. The scheduler is free to ignore
      * this hint. Yield is a heuristic attempt to improve relative progression between threads that would otherwise over-utilize a CPU.
      * Its use should be combined with detailed profiling and benchmarking to ensure that it actually has the desired effect.
      */
    
    public static native void yield();

    让我们列举一下关于以上定义重要的几点:

    Yield是一个静态的原生(native)方法 Yield告诉当前正在执行的线程把运行机会交给线程池中拥有相同优先级的线程。 Yield不能保证使得当前正在运行的线程迅速转换到可运行的状态 它仅能使一个线程从运行状态转到可运行状态,而不是等待或阻塞状态

    yield()方法使用示例

    在下面的示例程序中,我随意的创建了名为生产者和消费者的两个线程。生产者设定为最小优先级,消费者设定为最高优先级。在Thread.yield()注释和非注释的情况下我将分别运行该程序。没有调用yield()方法时,虽然输出有时改变,但是通常消费者行先打印出来,然后事生产者。

    调用yield()方法时,两个线程依次打印,然后将执行机会交给对方,一直这样进行下去。

    package test.core.threads;
    
    public class YieldExample
    {
       public static void main(String[] args)
       {
          Thread producer = new Producer();
          Thread consumer = new Consumer();
    
          producer.setPriority(Thread.MIN_PRIORITY); //Min Priority
          consumer.setPriority(Thread.MAX_PRIORITY); //Max Priority
    
          producer.start();
          consumer.start();
       }
    }
    
    class Producer extends Thread
    {
       public void run()
       {
          for (int i = 0; i < 5; i++)
          {
             System.out.println("I am Producer : Produced Item " + i);
             Thread.yield();
          }
       }
    }
    
    class Consumer extends Thread
    {
       public void run()
       {
          for (int i = 0; i < 5; i++)
          {
             System.out.println("I am Consumer : Consumed Item " + i);
             Thread.yield();
          }
       }
    }

    上述程序在没有调用yield()方法情况下的输出:

    I am Consumer : Consumed Item 0
     I am Consumer : Consumed Item 1
     I am Consumer : Consumed Item 2
     I am Consumer : Consumed Item 3
     I am Consumer : Consumed Item 4
     I am Producer : Produced Item 0
     I am Producer : Produced Item 1
     I am Producer : Produced Item 2
     I am Producer : Produced Item 3
     I am Producer : Produced Item 4

    上述程序在调用yield()方法情况下的输出:

    I am Producer : Produced Item 0
     I am Consumer : Consumed Item 0
     I am Producer : Produced Item 1
     I am Consumer : Consumed Item 1
     I am Producer : Produced Item 2
     I am Consumer : Consumed Item 2
     I am Producer : Produced Item 3
     I am Consumer : Consumed Item 3
     I am Producer : Produced Item 4
     I am Consumer : Consumed Item 4

    join()方法

    线程实例的方法join()方法可以使得在另一个线程的执行结束后再开始执行这个线程。如果join()方法被在一个线程实例上调用,当前运行着的线程将阻塞直到线程实例完成了执行。

    //Waits for this thread to die.
    
    public final void join() throws InterruptedException

    在join()方法内设定超时,使得join()方法的影响在特定超时后无效。当超时时,主方法和任务线程申请运行的时候是平等的。然而,当涉及sleep时,join()方法依靠操作系统计时,所以你不应该假定join()方法将会等待你指定的时间。

    像sleep,join通过抛出InterruptedException对中断做出回应。

    join()方法使用示例

    package test.core.threads;
    
    public class JoinExample
    {
       public static void main(String[] args) throws InterruptedException
       {
          Thread t = new Thread(new Runnable()
             {
                public void run()
                {
                   System.out.println("First task started");
                   System.out.println("Sleeping for 2 seconds");
                   try
                   {
                      Thread.sleep(2000);
                   } catch (InterruptedException e)
                   {
                      e.printStackTrace();
                   }
                   System.out.println("First task completed");
                }
             });
          Thread t1 = new Thread(new Runnable()
             {
                public void run()
                {
                   System.out.println("Second task completed");
                }
             });
          t.start(); // Line 15
          t.join(); // Line 16
          t1.start();
       }
    }
    
    Output:
    
    First task started
    Sleeping for 2 seconds
    First task completed
    Second task completed

    这是一些很小却很重要的概念。在评论部分让我知道你的想法。

    上一篇返回首页 下一篇

    声明: 此文观点不代表本站立场;转载务必保留本文链接;版权疑问请联系我们。

    别人在看

    Destoon 模板存放规则及语法参考

    Destoon系统常量与变量

    Destoon系统目录文件结构说明

    Destoon 系统安装指南

    Destoon会员公司主页模板风格添加方法

    Destoon 二次开发入门

    Microsoft 将于 2026 年 10 月终止对 Windows 11 SE 的支持

    Windows 11 存储感知如何设置?了解Windows 11 存储感知开启的好处

    Windows 11 24H2 更新灾难:系统升级了,SSD固态盘不见了...

    小米路由器买哪款?Miwifi热门路由器型号对比分析

    IT头条

    Synology 对 Office 套件进行重大 AI 更新,增强私有云的生产力和安全性

    01:43

    StorONE 的高效平台将 Storage Guardian 数据中心占用空间减少 80%

    11:03

    年赚千亿的印度能源巨头Nayara 云服务瘫痪,被微软卡了一下脖子

    12:54

    国产6nm GPU新突破!砺算科技官宣:自研TrueGPU架构7月26日发布

    01:57

    公安部:我国在售汽车搭载的“智驾”系统都不具备“自动驾驶”功能

    02:03

    技术热点

    最全面的前端开发指南

    Windows7任务栏桌面下角的一些正在运行的图标不见了

    sql server快速删除记录方法

    SQL Server 7移动数据的6种方法

    SQL Server 2008的新压缩特性

    每个Java程序员必须知道的5个JVM命令行标志

      友情链接:
    • IT采购网
    • 科技号
    • 中国存储网
    • 存储网
    • 半导体联盟
    • 医疗软件网
    • 软件中国
    • ITbrand
    • 采购中国
    • CIO智库
    • 考研题库
    • 法务网
    • AI工具网
    • 电子芯片网
    • 安全库
    • 隐私保护
    • 版权申明
    • 联系我们
    IT技术网 版权所有 © 2020-2025,京ICP备14047533号-20,Power by OK设计网

    在上方输入关键词后,回车键 开始搜索。Esc键 取消该搜索窗口。