原文地址:http://www.geeksforgeeks.org/java-concurrency-yield-sleep-and-join-methods/
我们可以通过Thread类中的下面几个方法阻止线程的执行。
yield()
假设有三个线程t1,t2和t3。线程t1得到了处理器并且开始执行,线程t2和t3在等待/可执行状态。t1需要5小时可以完成,t2需要5分钟可以完成。因为t1在5个小时以后才能完成,那么t2想要完成5分钟的任务那就得等5个小时。在这种情景下一个线程为了完成它的执行就花费的时间太久了,我们需要一个方法在有正要的事情发生的时候可以阻止线程的执行。yield()
就可以帮我们做这样的事情。
yield()实际上就是当一个线程所执行的任务不是那么重要的时候,这时候其他的线程或者进程需要执行了,那么就让这些线程或者进程执行。否则的话,当前的线程继续执行。
yield的用法
- 无论啥时候一个线程调用java.lang.Thread.yield方法,它都会通知线程调度程序准备暂停线程的执行。线程调度器可以随意忽略这样的提示。
- 如果优先从执行了yield方法,线程调度程序就会检查是否有线程比它有相同的或者更高的优先级。如果处理器找到了与它相同或者更高优先级的线程,那么处理器就会移除当前线程到准备/可执行状态,并将处理器分配给其他线程,如果没找到,那就当前线程继续执行呗。
语法
public static native void yield()
// Java program to illustrate yield() method in Java
import java.lang.*;
// MyThread extending Thread
class MyThread extends Thread {
public void run() {
for (int i=0; i<5 ; i++)
System.out.println(Thread.currentThread().getName() + " in control");
}
}
// Driver Class
public class yieldDemo {
public static void main(String[] args) {
MyThread t = new MyThread();
t.start();
for (int i = 0; i < 5; i++) {
// Control passes to child thread
Thread.yield();
// After execution of child Thread
// main thread takes over
System.out.println(Thread.currentThread().getName() + " in control");
}
}
}
输出:
Thread-0 in control
Thread-0 in control
Thread-0 in control
Thread-0 in control
Thread-0 in control
main in control
main in control
main in control
main in control
main in control
输出的结果可能在不同的机器上不一样,但是yield()过的线程是比其他线程执行的机会要高的,因为main线程总是暂停它的执行,并给相同优先级的子线程机会执行。
注意
- 一旦一个线程执行了yield方法,那么就会有许多优先级相同的线程都在等待处理器,那么我们就不能指定那个线程有最先执行的机会了。
- 执行了yield方法的线程将从运行状态进入可运行状态。
- 一旦一个线程暂停了它的执行,那么我们就不能干预了,它的再次执行就全看线程调度程序了。
- 如果我们要用yield方法,那么底层平台就必须得提供抢先调度(preemptive scheduling)的支持。
sleep()
这个方法会让当前执行的程序睡眠指定的时间,这个受限于系统时间和调度程序的准确度。
语法
// 睡眠指定的毫秒数
public static void sleep(long millis) throws InterruptedException
//睡眠指定的毫秒数+纳秒
public static void sleep(long millis, int nanos) throws InterruptedException
// Java program to illustrate
// sleep() method in Java
import java.lang.*;
public class SleepDemo implements Runnable {
Thread t;
public void run() {
for (int i = 0; i < 4; i++) {
System.out.println(Thread.currentThread().getName() + " " + i);
try {
// thread to sleep for 1000 milliseconds
Thread.sleep(1000);
}
catch (Exception e) {
System.out.println(e);
}
}
}
public static void main(String[] args) throws Exception {
Thread t = new Thread(new SleepDemo());
// call run() function
t.start();
Thread t2 = new Thread(new SleepDemo());
// call run() function
t2.start();
}
}
yield() vs sleep()
yield()指的是线程在没有做特别重要的任务的时候,如果其他线程或者进程需要执行,那么就会执行。否则当前线程继续执行就行了。
sleep()是说线程确实需要停止执行指定的一段时间,如果没有其他的线程或者进程需要执行,那么CPU将处于空闲(也可能进入省电模式)
join()
Thread实例的join方法是用于连接开始一个线程的执行到结束另一个线程的执行,这样线程就不用在另一个线程执行完了才开始执行。如果一个Thread实例调用join()
,那么当前执行的线程就会受阻知道这个线程的智力执行完毕。
join()
方法最多等到这个线程死亡,将超时设为0意思就是永不超时或者永远等待。
语法
// 等待线程死亡
public final void join() throws InterruptedException
// 最多等待这么多毫秒
public final void join(long millis) throws InterruptedException
// 最多等待这么多毫秒+纳秒
The java.lang.Thread.join(long millis, int nanos)
// Java program to illustrate join() method in Java
import java.lang.*;
public class JoinDemo implements Runnable {
public void run() {
Thread t = Thread.currentThread();
System.out.println("Current thread: " + t.getName());
// checks if current thread is alive
System.out.println("Is Alive? " + t.isAlive());
}
public static void main(String args[]) throws Exception {
Thread t = new Thread(new JoinDemo());
t.start();
// Waits for 1000ms this thread to die.
t.join(1000);
System.out.println("\nJoining after 1000" + " mili seconds: \n");
System.out.println("Current thread: " + t.getName());
// Checks if this thread is alive
System.out.println("Is alive? " + t.isAlive());
}
}
输出:
Current thread: Thread-0
Is Alive? true
Joining after 1000 mili seconds:
Current thread: Thread-0
Is alive? false
注意:
- 如果任意一个执行的线程t1在t2上调用
join()
,例如t2.join()
,那么t1会马上进入等待状态,直到t2完成执行。 - 已知在join()中产生了超时,那么这将使得
join()
的作用在超时之后被抵消。