Java多线程之join及yield解读

join()

在java源码中,join解读为下

    /**
     * Waits for this thread to die.
     *
     * 

An invocation of this method behaves in exactly the same * way as the invocation * *

* {@linkplain #join(long) join}{@code (0)} *
* * @throws InterruptedException * if any thread has interrupted the current thread. The * interrupted status of the current thread is * cleared when this exception is thrown. */
public final void join() throws InterruptedException { join(0); }

翻译过后大概就是:1 等待线程死亡 2 此方法的调用行为完全相同
点击进入join(0),可以看到源码

public final synchronized void join(long millis) throws InterruptedException {
  long base = System.currentTimeMillis();
  long now = 0;
  if (millis < 0) {
   throw new IllegalArgumentException("timeout value is negative");
  }
  if (millis == 0) {//在此
   while (isAlive()) {
    wait(0);
   }
  } else {
   while (isAlive()) {
    long delay = millis - now;
    if (delay <= 0) {
     break;
    }
    wait(delay);
    now = System.currentTimeMillis() - base;
   }
  }
 }

我们可以理解为如果join的方法在线程实例中被调用,当前运行的线程会被堵塞,直到线程实例运行完成。
如线程a中调用线程b的join方法,这时线程a就会进入阻塞状态,直到线程b执行完成。这样就可以使并行的线程串行化的执行。
话不多说,代码如下:

//线程1
 static class MyThread01 implements Runnable {
  private String str;
  public MyThread01(String str) {
   this.str = str;
  }
  @Override
  public void run() {
   Thread.currentThread().setName(str);//赋值线程name
   for (int j = 0; j < 10; j++) {
    System.out.println(Thread.currentThread().getName() + "," + j);
   }
  }
 }
 //线程2
 static class MyThread02 implements Runnable {
  private String str;
  public MyThread02(String str) {
   this.str = str;
  }
  @Override
  public void run() {
   Thread.currentThread().setName(str);//赋值线程name
   for (int j = 10; j > 0; j--) {
    System.out.println(Thread.currentThread().getName() + "," + j);
   }
  }
 }
 public static void main(String[] args) {
  Thread thread01 = new Thread(new MyThread01("A"));
  Thread thread02 = new Thread(new MyThread02("B"));
  thread01.start();
  //thread01.join();//先注释
  thread02.start();
 }

未使用join方法,输出如下

B,0
A,0
B,1
A,1
B,2
A,2
B,3
A,3
B,4
B,5
B,6
A,4
B,7
B,8
B,9
A,5
A,6
A,7
A,8
A,9

当我们使用join方法后,输出结果为下

A,0
A,1
A,2
A,3
A,4
A,5
A,6
A,7
A,8
A,9
B,10
B,9
B,8
B,7
B,6
B,5
B,4
B,3
B,2
B,1

可以看出join方法可以使得一个线程在另一个线程结束后再执行

yield()

先贴源码,虽说这玩意有点装x,但没事的时候可以看一下,不懂就百度。。。慢慢也能多多少少提升一点点

/**
     * 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-utilise a CPU. Its use * should be combined with detailed profiling and benchmarking to * ensure that it actually has the desired effect. * *

It is rarely appropriate to use this method. It may be useful * for debugging or testing purposes, where it may help to reproduce * bugs due to race conditions. It may also be useful when designing * concurrency control constructs such as the ones in the * {@link java.util.concurrent.locks} package. */ public static native void yield();

核心的一句话就是 : 向调度程序提示当前线程愿意让步
yield意味着放手,一个调用yield()方法的线程告诉虚拟机它乐意让其他线程占用自己的位置。假设有个玩具,自己玩完后将之放下,它可以让弟弟妹妹去抢,当然,自己也没玩够,也可以去抢,最后谁抢到就谁玩。
接下来就是代码展示,为了可以体现处yield的效果,我们可以设置一下线程的优先级,代码可以看出这个优先级像我上篇提到的,并不能保证先后顺序。

/**
 * @version:1.0
 * @Description: join 及  yeiled
 * @author: mjx
 * @date: 2019年4月10日
 */
public class DemoConcurrent_04 {
 //线程1
 static class MyThread01 extends Thread {
  private String str;
  public MyThread01(String str) {
   this.str = str;
  }
  @Override
  public void run() {
   Thread.currentThread().setName(str);//赋值线程name
   for (int j = 0; j < 5; j++) {
    System.out.println(Thread.currentThread().getName() + "," + j);
    //yield();//先注释
   }
  }
 }
 //线程2
 static class MyThread02 extends Thread {
  private String str;
  public MyThread02(String str) {
   this.str = str;
  }
  @Override
  public void run() {
   Thread.currentThread().setName(str);//赋值线程name
   for (int j = 5; j > 0; j--) {
    System.out.println(Thread.currentThread().getName() + "," + j);
    //yield();//先注释
   }
  }
 }
 public static void main(String[] args) throws InterruptedException {
  MyThread01 thread01 =new MyThread01("A");
  MyThread02 thread02 =new MyThread02("B");
  //设置后理论上默认max线程会先打印(但根据机器而定)
  thread01.setPriority(Thread.MIN_PRIORITY); //Min Priority
  thread02.setPriority(Thread.MAX_PRIORITY); //Max Priority
  thread01.start();
  thread02.start();
 }
}

未使用yield输出结果为

A,0
B,5
B,4
B,3
B,2
B,1
A,1
A,2
A,3
A,4

使用yield输出结果为

B,5
A,1
B,4
A,2
B,3
A,3
B,2
A,4
B,1

注意:具体的打印结果并不是一定的,而且yield的使用并不意味着会使线程间交替执行,切记。

希望这些很小却很重要的概念可以帮到你,也希望在评论部分鼓励一下我,谢谢大家!

你可能感兴趣的:(Java多线程)