启动
使用start()方法可以启动线程。
start()方法的含义是告知线程规划器线程已初始化完毕,可以分给这个线程时间片了(执行run()方法)。
安全终止线程
示例代码
import java.util.concurrent.TimeUnit;
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;
}
}
}
结果
Count i = 364902562
Count i = 239832801
分析:使用【中断操作】和【volatile修饰的停止标识变量】这两种方式都能够优雅安全地停止线程
代码中target为one时是使用interrupt(),运行中的线程(main主线程)调用线程countThread的interrupt()方法,向countThread线程打了个“招呼”,对countThread线程做了中断操作。我们看JDK源码中interrupt()方法的源码:
看注释:
// Just to set the interrupt flag
说的非常明白,对标识位进行了设置。就是将 interrupt flag 设置为true。将线程的中断标识位 interrupt flag 属性设置为了true。
所以while条件中 Thread.currentThread().isInterrupted() 返回为true。然后代码跳出了while循环。
代码中target为two时是显式地将停止标识变量on(为volatile变量)变为false,然后跳出while循环。
为何说这样停止线程的方式安全优雅?
Thread的stop()方法也可以终止线程,但是很直接暴力,而且可能会引起死锁。
所以stop()方法被被遗弃了。
使用【中断操作】和【volatile修饰的停止标识变量】的方式停止线程,使线程在终止时有机会清理资源。
安全终止线程套路总结
1.run()方法中一般都有while条件。
2.将停止标识变量(最好定义为volatile变量,多线程场景下能够立马读取该变量)写入while条件。
3.显式的调用改变停止标识变量的方法,就可以安全而优雅的停止线程了。