Java的线程支持提供了一些快捷的工具方法,通过这些快捷的工具方法可以很好地控制线程的执行。
1、join线程
Thread提供了让一个线程等待另一个线程完成的方法—join()方法。当在某个程序执行流中调用其他线程的join方法时,调用线程将被阻塞,直到join方法加入的join线程执行完为止。
举个例子:
public class JoinThread extends Thread{
//提供一个有参数的构造器,用于设置该线程的名字
public JoinThread(String name) {
super(name);
}
public void run() {
for(int i = 0; i < 100; i++) {
System.out.println(getName() + " " + i);
}
}
public static void main(String[] args) throws InterruptedException {
new JoinThread("新线程").start();
for(int i = 0; i < 100; i++) {
if(i == 20) {
JoinThread jT = new JoinThread("被Join的线程");
jT.start();
//main线程调用了jT线程的join方法,main线程必须等jT执行结束后才会向下执行
jT.join();
}
System.out.println(Thread.currentThread().getName() + " " + i);
}
}
}
上面程序中一共有三个线程,主方法开始时就启动了名为“新线程”的子线程,该线程将会和主线程并发执行。从下图可以看出。
当主线程的循环变量i等于20时,启动了名为“被join的线程”,该线程不会和main线程并发执行,main线程必须等待该线程执行结束后才可以向下执行。此时,只有名为“被join的线程”和名为“新线程”两个线程执行,而主线程处于阻塞状态。
从上图可以看出,直到名为“被join的线程”的线程执行完毕后,主线程才继续执行。
join()方法有如下三种重载方式:
join(): 等待被join的线程执行完成。
join(long millis): 等待被join的线程的时间最长为millis毫秒。如果在millis毫秒内被join的线程还没有结束,则不再等待。
join(long millis, int nanos) : 等待被join的线程的时间最长为millis毫秒加nanos豪微妙。
2、线程睡眠sleep
如果需要让当前正在执行的线程暂停一段时间,并进入阻塞状态,则可以通过调用Thread类的静态sleep()方法来实现。形式如下:
static void sleep(long millis) : 让正在执行的线程暂停掉millis毫秒,并进入阻塞状态。
static void sleep(long millis, int nanos): 让当前正在执行的线程暂停millis毫秒加nanos微毫秒,并进入阻塞状态。
当当前线程调用sleep()方法进入阻塞状态后,在其睡眠时间内,该线程不会获得执行的机会。即使系统中没有其他可以执行的线程,处于sleep()中的线程也不会执行。因此sleep()方法一般用来暂停程序的执行。
举个例子:
import java.util.Date;
import javax.xml.crypto.Data;
public class SleepTest {
public static void main(String[] args) throws InterruptedException {
for(int i = 0; i < 10; i++) {
System.out.println("当前时间:" + new Date());
Thread.sleep(1000);
}
}
}
上面程序依次输出10条字符串,输出第二条字符串之间的时间间隔为1秒。
3、后台线程
有一种线程,它是在后台运行的,它的任务是为其他的线程提供服务,这种线程被称为“后台线程”,又称为“守候线程”、或者“精灵线程”。JVM的垃圾回收线程就是典型的后台线程。
后台线程有个特征:如果所有前台的线程都死亡,后台线程会自动死亡。
调用Thread对象的setDanmon(true)方法可将指定线程设置成后台线程。
Thread类还提供了一个isDanmon()方法判断指定线程是否为后台线程。