一、sleep()

1.1 sleep()简介

  sleep() 的作用是让当前线程休眠,即当前线程会从“运行状态”进入到“休眠(阻塞)状态”。在线程重新被唤醒时,它会由“阻塞状态”变成“就绪状态",从而等待cpu的调度执行。
  sleep()会指定休眠时间,线程休眠的时间会大于/等于该休眠时间。

1.2 sleep()的使用

  Thread.sleep(100);

1.3 sleep()与wait()区别

  wait 和 sleep都会造成某种形式的暂停。wait()用于线程间通信,作用是让当前线程由“运行状态”进入”等待(阻塞)状态”;而sleep()的作用是让当前线程由“运行状态”进入到“休眠(阻塞)状态”。
  wait()会释放对象的同步锁;而sleep()则不会释放锁,仅仅释放CPU资源或者让当前线程停止执行一段时间。

二、join()

2.1 join()简介

  如果一个线程A执行了thread.join()语句,其含义是:当前线程A等待thread线程终止之后才从thread.join()返回。
  线程Thread除了提供join()方法之外,还提供了join(long millis)和join(long millis,int nanos)两个具备超时特性的方法。这两个超时方法表示,如果线程thread在给定的超时时间里没有终止,那么将会从该超时方法中返回。

2.2 join()示例

有三个线程T1,T2,T3,怎么确保它们按顺序执行?

/**
 * 有三个线程T1,T2,T3,怎么确保它们按顺序执行?
 * join()
 * @author lc 2017/5/3
 */
public class TestJoin {
    public static void main(String[] args) {        
        final Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName());
            }
        },"T1");

        final Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    t1.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName());
            }
        },"T2");

        Thread t3 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    t2.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName());
            }
        },"T3");

        t3.start();
        t2.start();
//      try {
//          Thread.sleep(300);
//      } catch (InterruptedException e) {
//          e.printStackTrace();
//      }
        t1.start();
    }
}

输出结果:T1
     T2
     T3

2.3 join()源码

1.join()方法

public final void join() throws InterruptedException {
        join(0); //实际是调用join(long millis)
}

2.join(long millis)方法

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");
        }

        //join()方法。join(0)
        if (millis == 0) {
            while (isAlive()) {//判断本线程是否为活动状态(活动状态指线程已经启动且尚未终止)
                wait(0); //等待
            }
        } else {
            while (isAlive()) {
                long delay = millis - now;
                if (delay <= 0) {
                    break;
                }
                wait(delay);
                now = System.currentTimeMillis() - base;
            }
        }
    }

三、yield()

3.1 yield()简介

  yield()的作用是让步。它能让当前线程由“运行状态”进入到“就绪状态”,从而让其它具有相同优先级的等待线程获取执行权。但是,并不能保证在当前线程调用yield()之后,其它具有相同优先级的线程就一定能获得执行权,也有可能是当前线程又进入到“运行状态”继续运行!

3.2 yield()的使用

  Thread.yield();

3.3 为什么Thread类的sleep()和yield()方法是静态的?

  Thread类的sleep()和yield()方法将在当前正在执行的线程上运行,其他处于等待状态的线程调用这些方法是没有意义的。将这些方法设计成静态的,可以在当前正在执行的线程中工作,并避免程序员错误的认为可以在其他非运行线程调用这些方法。

参考资料
《java并发编程的艺术》