大厂之路一由浅入深、并行基础、源码分析一加入J、谦让Y

在这里插入图片描述

  • 谦让yield()
    • yield() 定义在Thread.java中,而不是Object中。
    • 作用:
      • 让步。它能让当前线程由 “运行状态”—>“就绪状态”,从而让其它具有相同优先级的等待线程获取执行权;但是,并不能保证在当前线程调用yield()之后,其它具有相同优先级的线程就一定能获得执行权;也有可能是当前线程又进入到“运行状态”继续运行!
      • 和sleep类似,让线程从“运行状态”到“就绪状态”,但是不会阻塞线程,只是让当前线程停一会儿,让同优先级的其他线程获得被执行的机会,但是不保证一定会被执行。
    • 源码: 在这里插入图片描述
      • 这是一个静态方法,本地方法。一旦执行,它会使当前线程让出CPU。但要注意,让出CPU不代表它不执行了。虽然让出CPU,它还会进行CPU资源的争夺,但是能否被再次分配到就不一定了。
      • 因此,yield()的寓意就是:我已经完成了一些最重要的工作了,我可以休息一下了。
    • yield()示例
package com.wwj.text;

public class  WaitTest{
    public static void main(String[] args){
        Thread t1 = new ThreadA("t1");
        Thread t2 = new ThreadA("t2");
        t1.start();
        t2.start();
    }
}
class ThreadA extends Thread{
    public ThreadA(String name){
        super(name);
    }
    @Override
    public synchronized void run() {
        for(int i=0 ; i<5 ;i++){
            System.out.print(this.getName()+"["+this.getPriority()+"]"+":"+i+" ");
            if(i % 4 == 0){
                Thread.yield();
            }
        }
    }
}
  • 结果:
    • t1[5]:0 t2[5]:0 t1[5]:1 t2[5]:1 t1[5]:2 t2[5]:2 t1[5]:3 t2[5]:3 t1[5]:4 t2[5]:4
    • “线程t1”在能被4整数的时候,并没有切换到“线程t2”。这表明,yield()虽然可以让线程由“运行状态”进入到“就绪状态”;但是,它不一定会让其它线程获取CPU执行权(即,其它线程进入到“运行状态”),即使这个“其它线程”与当前调用yield()的线程具有相同的优先级。

  • 等待线程结束join()
    • join() 定义在Thread.java中,而不是Object中
    • join()也是“加入”的意思,也就是一个线程要加入另外一个线程,最好的方法就是等着它(另外一个线程执行完)一起走。
    • 作用: “主线程”等待“子线程”结束之后 才能继续运行。
    • 具体来讲:一个线程的输入可能非常依赖于另外一个或者多个线程的输出,此时,这个线程就需要等待依赖线程执行完毕,才能继续执行。
    • 两个join()方法:
      • public final void join() throws InterruptedException { join(0);}
        • 代表无限等待,类似wait(),它会一直阻塞当前进程,直到目标进程执行完毕
      • public final synchronized void join(final long millis) thows InterruptedException{}
        • 给了一个最大等待时间,类似于有参数的wait( long millis),超时则不等待
    • join()示例:
package com.wwj.text;

public class JoinMain {
    public volatile  static int i=0;
    public static class AddThread extends  Thread{
        @Override
        public void run() {
            for(i=0 ; i<10000000  ; i++);
        }
    }
    public static void main(String[] args) throws InterruptedException{
        Thread at = new AddThread();
        at.start();
        at.join();
        System.out.println(i);
    }
}
  • 结果:
    • 10000000 , 如果去除at.join();,结果为0
    • 说明如果不使用join()方法等待AddThread,那么得到的i可能是0或者很小,因为AddThread还没开始执行,i的值就已经被输出了。但是使用join()方法后,表示 主线程愿意等待AddThread执行完毕,跟着AddThread一起往前走,因此在join()使用后,AddThread已经执行完成,因此i总是10000000
    • 一个很困惑的点:执行join()的线程为目的线程,是要等这个线程执行完即可
  • 进一步说明join()的用法:让“主线程”线程等待“子线程”运行完之后再运行
//子线程
public class son extends Thread(){
        void run(){
        ......
        }
}
//主线程
public class F() extends Thread{
        void run(){
        son s = new son();
        s.start();
        s.join();
        ...
     }
}
  • 在主线程中调用子线程s.start()启动子线程并调用s.join(),在调用s.join()之后主线程(F)会一直等待,直到子线程(son)运行完毕之后才接着运行
  • join()源码分析: 在这里插入图片描述
    • 注意的是:类似wait()、notify()方法不要在Thread对象实例上进行使用,因此很可能影响系统API的工作,或者被系统API影响。

  • sleep()、wait()、notify()、yield()、join()有什么相同不同点?
    • wait()、notify() 是一对,当然这5个都可以单用。
    • sleep()、join()、yield()属于Thread.java,wait()、notify()属于Object.java
    • wait()让线程从“运行状态”到“阻塞状态”,yield让线程从“运行状态”到“就绪状态”
    • wait()和notify()的使用要和“synchronized”内使用,这也是它们属于Object的理由
    • wait()会释放同步锁,sleep()不会释放占用资源,yield()释放占用资源,但是同样也会继续争抢。
  • yield() 与 wait()的比较
    • 我们知道,wait()的作用是让当前线程由“运行状态”进入“等待(阻塞)状态”的同时,也会释放同步锁。
    • 而yield()的作用是让步,它也会让当前线程离开“运行状态”。它们的区别是:
      • wait()是让线程由“运行状态”进入到“等待(阻塞)状态”,而yield()是让线程由“运行状态”进入到“就绪状态”。
      • wait()是会线程释放它所持有对象的同步锁,yield()方法不会释放锁。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值