通過調用線程的start()方法進行啟動,隨著run()方法的執行完畢,線程也隨之終止。
一、啟動線程
線程對象在初始化完成后,調用start()方法就可以啟動這個線程。線程start()方法的含義是:當前線程(即parent線程)同步告知Java虛擬機,只要線程規劃器空閑,應立即啟動調用start()方法的線程。
啟動一個線程前,最好為這個線程命名,方便用jstack等工具分析程序進行問題排查。
二、理解中斷
中斷好比其他線程對該線程打了個招呼,前天線程通過調用該線程的interrupt()方法對其進行中斷操作。
線程通過isInterrupted()來進行判斷是否被中斷,也可以調用靜態方法Thread.interrupted()對當前線程的中斷標識進行復位。
從Java的API中可以看到,許多聲明拋出InterruptedException的方法(例如Thread.sleep(long millis)方法)在拋出InterruptedException之前,Java虛擬機會先將該線程的中斷標識位清除,然后拋出InterruptedException,此時調用isInterrupted()方法將會返回false。
通過下面的示例可以證明:
public class Interrupted {
public static void main(String[] args) throws Exception {
// sleepThread不停的嘗試睡眠
Thread sleepThread = new Thread(new SleepRunner(), "SleepThread");
sleepThread.setDaemon(true);
// busyThread不停的運行
Thread busyThread = new Thread(new BusyRunner(), "BusyThread");
busyThread.setDaemon(true);
sleepThread.start();
busyThread.start();
// 休眠5秒, 讓sleepThread和busyThread充分運行
TimeUnit.SECONDS.sleep(5);
sleepThread.interrupt();
busyThread.interrupt();
System.out.println("SleepThread interrupted is " + sleepThread.isInterrupted());
System.out.println("BusiThread interrupted is " + busyThread.isInterrupted());
// 防止sleepThread和busiThread立即退出
SleepUtils.second(2);
}
static class SleepRunner implements Runnable {
@Override
public void run() {
while (true) {
SleepUtils.second(10);
}
}
}
static class BusyRunner implements Runnable {
@Override
public void run() {
while (true) {
}
}
}
}
輸出如下:
SleepThread interrupted is false
BusyThread interrupted is true
三、安全地終止線程
除中斷操作外,還可以利用boolean變量來控制是否需要停止任務并終止該線程。
示例代碼,創建了一個線程CountThread,它不斷地進行變量累加,而主線程嘗試對其進行中斷操作和停止操作:
public class Shutdown {
public static void main(String[] args) throws Exception {
Runner one = new Runner();
Thread countThread = new Thread(one, "CountThread");
countThread.start();
// 睡眠1秒, main線程對CountThread進行中斷, 使CountThread能夠感知中斷而結束
TimeUnit.SECONDS.sleep(1);
countThread.interrupt();
Runner two = new Runner();
countThread = new Thread(two, "CountThread");
countThread.start();
// 睡眠1秒, main線程對Runner two進行取消, 使CountThread能夠感知on為false而結束
TimeUnit.SECONDS.sleep(1);
two.cancel();
}
private static class Runner implements Runnable {
private long i;
private volatile boolean on = true;
@Override
public void run() {
while (on && !Thread.currentThread().isInterrupted()) {
i++;
}
System.out.println("Count i = " + i);
}
public void cancel() {
on = false;
}
}
}