1.start()和run()
执行的线程,一定要调用它的start()方法。不能调用run()方法。

如果直接调用线程对象的run()方法,程序也会执行,但那样是在当前线程中执行,不会启动新的线程。

start()方法的本质是从CPU中申请一个新的线程空间来执行 run()方法中的代码。
run()方法的本质是只是线程的接口回调方法。

一个线程对象只能运行成功一次start()方法,即
已经调用start()方法的对象不能再次调用start()方法,否则会抛异常。

2.sleep()
sleep()是静态方法,使正在运行的线程进入
TIMED_WAITING状态,但不释放对象锁
睡眠时间到了,会进入就绪状态。

给其他线程执行机会。

sleep()方法声明抛出了InterruptedException

在sleep 时间间隔期满后,线程不一定立即恢复执行,
即:
Thread.sleep(1000)使得线程睡眠1秒,可能结果会大于1秒
除非:
a.醒来的线程具有更高的优先级。
b.正在运行的线程因为其它原因而阻塞。
所以:
程序员只能最大限度的影响线程执行的次序,而不能做到精准控制。

sleep()方法是静态方法,只对正在运行状态的线程对象有效。如:

public class TestThread {
 public static void main(String[] args) throws InterruptedException {
  System.out.println(Thread.currentThread().getName());
  Thread threadNew=new Thread();
  threadNew.start();
  //这里是主线程sleep,而不是threadNew线程
  threadNew.sleep(1000);
  System.out.println(Thread.currentThread().getName());
  Thread.sleep(10);
  for(int i=0;i<100;i++){
   System.out.println("main"+i);
  }
 }
}

3.yield()
yield()是静态方法,使正在运行的线程进入就绪状态,
不释放对象锁

yield()方法声明没有抛出异常。

yield()方法是让系统的线程调度器重新调度当前线程。让相同优先级的线程轮流执行,但并不保证一定会轮流执行。
可能:
当某个线程调用yield()方法之后,线程调度器又将其调度出来重新进入到运行状态执行。

比较:

3.1 yield()方法和sleep()方法,都是Thread类的静态方法。

3.2 yield()方法让线程进入就绪状态。sleep()方法让线程进入阻塞状态,睡眠时间到了,再进入就绪状态。

3.3 sleep()、wait()、join() 都抛出了InterruptedException,yield()没有。

3.4 通常不用yield()方法,因为移植性不好。而用sleep()方法。

4.join()
将几个并行线程的线程合并为一个单线程执行,

应用场景是当一个线程必须等待另一个线程执行完毕才能执行时,

它不是静态方法。
它有3个重载的方法:
void join()   
     当前线程等该加入该线程后面,等待该线程终止。   
void join(long millis)   
     当前线程等待该线程终止的时间最长为 millis 毫秒。 如果在millis时间内,该线程没有执行完,那么当前线程进入就绪状态,重新等待cpu调度  
void join(long millis,int nanos)   
     等待该线程终止的时间最长为 millis 毫秒 + nanos 纳秒。如果在millis时间内,该线程没有执行完,那么当前线程进入就绪状态,重新等待cpu调度 

 

public class Test1 {
 public static void main(String[] args) throws InterruptedException {
  MyThread thread=new MyThread();
  thread.start();
  thread.join(1);//将主线程加入到子线程后面,不过如果子线程在1毫秒时间内没执行完,则主线程便不再等待它执行完,进入就绪状态,等待cpu调度
  for(int i=0;i<30;i++){
   System.out.println(Thread.currentThread().getName() + "线程第" + i + "次执行!");
  }
 }
}

class MyThread extends Thread {
 @Override
 public void run() {
  for (int i = 0; i < 1000; i++) {
   System.out.println(this.getName() + "线程第" + i + "次执行!");
  }
 }
}

在这个例子中,在主线程中调用thread.join(); 就是将主线程加入到thread子线程后面等待执行。不过有时间限制,为1毫秒。