sleep()
让调用它的线程暂停多长时间再执行该线程,由运行状态变为阻塞状态,可以调节每个线程什么时候执行,且不会释放资源。当调用Thread.sleep(long millis)睡眠方法时,就会使当前线程进入阻塞状态。milis参数指定了线程睡眠的时间,单位是毫秒。当时间结束之后,线程会重新进入就绪状态。注意,如果当前线程获得了一把同步锁,则sleep方法阻塞期间,是不会释放锁的。
join()
当线程调用另外一个线程的join方法时,当前线程就会进入阻塞状态。直到另外一个线程执行完毕,当前线程才会由阻塞状态转为就绪状态。
public class Test {
public static void main(String[] args) {
Thread t1 = new Thread("t1线程") {
@Override
public void run() {
try {
//t1线程睡眠1秒钟
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("t1线程结束");
}
};
Thread t2 = new Thread("t2线程") {
@Override
public void run() {
try {
//t2线程调用t1.join方法
//t2线程进入阻塞状态
//t2线程要等到t1线程运行结束,才能恢复到RUNNABLE状态
t1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("t2线程结束");
}
};
t1.start();
t2.start();
//让主线程休眠500毫秒,目的是为了给t1和t2点时间,让他们俩个线程进入状态
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(t2.getState());
}
}
//运行结果
//WAITING
//t1线程结束
//t2线程结束
yield()
Thread.yield 方法会使当前线程放弃CPU时间片,把执行机会让给相同或更高优先级的线程(yield英文意思就是屈服,放弃的意思嘛,可以理解为当前线程暂时屈服于别人了)。
注意,此时当前线程不会阻塞,只是进入了就绪状态,随时可以再次获得CPU时间片,从而进入运行状态。也就是说,其实yield方法,并不能保证,其它相同或更高优先级的线程一定会获得执行权,也有可能,再次被当前线程拿到执行权。
yield方法和sleep方法一样,也是不释放锁资源的。
yield一般用于不存在锁竞争的多线程环境中。如果当前线程执行的任务时间可能比较长,就可以选择用yield方法,暂时让出CPU执行权。让其它线程也有机会执行任务,而不至于让CPU资源一直消耗在当前线程。
wait()、notify()、notifyAll()
首先,它们都是Object类中的方法。需要配合 synchronized关键字来使用。
调用线程的wait方法会使当前线程等待,直到其它线程调用此对象的notify/notifyAll方法。如果,当前对象锁有N个线程在等待,则notify方法会随机唤醒其中一个线程,而notifyAll会唤醒对象锁中所有的线程。需要注意,唤醒时,不会立马释放锁,只有当前线程执行完之后,才会把锁释放。
另外,wait方法和sleep方法不同之处,在于sleep方法不会释放锁,而wait方法会释放锁。