方法一、程序正常运行结束
线程体执行完成了,那么线程也就自动结束了。
方法二、使用stop方法
这是一个被弃用的方法,打开Thread类可以看到它是被@Deprecated注解修饰的,非常不推荐使用这个方法
@Deprecated
public final void stop() {
SecurityManager security = System.getSecurityManager();
if (security != null) {
checkAccess();
if (this != Thread.currentThread()) {
security.checkPermission(SecurityConstants.STOP_THREAD_PERMISSION);
}
}
// A zero status value corresponds to "NEW", it can't change to
// not-NEW because we hold the lock.
if (threadStatus != 0) {
resume(); // Wake up thread if it was suspended; no-op otherwise
}
// The VM can handle all thread states
stop0(new ThreadDeath());
}
在程序中直接使用Thread.stop方法强行终止线程,是很危险的,就像突然关闭计算机的电源,而不是正常关机,可能会产生不可预料的后果。
在程序中使用Thread.stop方法终止线程时,该线程的子线程会抛出ThreadDeatherror错误,并且释放子线程持有的所有的锁。
加锁的代码块一般用于保护数据的一致性,如果在调用Thread.stop方法后导致该线程所持有的所有锁突然释放而使锁资源不可控制,被保护的数据就可能出现不一致的情况,其他线程在使用这些被破坏的数据时,有可能使程序运行错误。
测试看看:
public class TerminateThread implements Runnable {
@Override
public void run() {
int i = 0;
while(true) {
System.out.println("i:" + (i++));
}
}
public void startThread() {
Thread thread = new Thread(new TerminateThread());
thread.start();
for(int i = 0; i <= 10; i++) {
if(i == 9) {
thread.stop();//调用stop方法
System.out.println("线程终止");
break;
}
System.out.println("main-->" + i);
}
}
public static void main(String[] args) {
TerminateThread t = new TerminateThread();
t.startThread();
}
}
输出结果:
main-->0
main-->1
main-->2
main-->3
main-->4
main-->5
i:0
main-->6
main-->7
main-->8
i:1i:1线程终止
可以看到最后i= 1输出了两遍
方法三、使用退出标志
用一个变量来判断线程是否结束
/**
* 终止线程
* 1、 线程执行完毕
* 2、 外部标志位(不要使用stop、destroy,不安全)
*/
public class TerminateThread {
//加入标识,标记线程体是否可以运行
private static boolean flag = true;//
public void terminate() {
this.flag = false;
}
public static void main(String[] args) {
TerminateThread tt = new TerminateThread();
new Thread(() -> {
int i = 0;
while(flag) {
System.out.println("i:" + (i++));
}
}).start();
for(int i = 0; i <= 10; i++) {
if(i == 9) {
tt.terminate();
System.out.println("线程终止");
break;
}
System.out.println("main-->" + i);
}
}
}
输出结果:
main-->0
main-->1
main-->2
main-->3
main-->4
main-->5
main-->6
i:0
i:1
i:2
i:3
i:4
i:5
i:6
i:7
i:8
i:9
main-->7
main-->8
i:10
线程终止
使用volatile关键字来修饰标志符更佳
public class TerminateThread {
//加入标识,标记线程体是否可以运行
// private static boolean flag = true;//
// public void terminate() {
// this.flag = false;
// }
static volatile boolean flag = true;
public static void main(String[] args) {
TerminateThread tt = new TerminateThread();
new Thread(() -> {
int i = 0;
while(flag) {
System.out.println("i:" + (i++));
}
}).start();
for(int i = 0; i <= 10; i++) {
if(i == 9) {
flag = false;
System.out.println("线程终止");
break;
}
System.out.println("main-->" + i);
}
}
}
输出结果:
main-->0
main-->1
main-->2
main-->3
main-->4
main-->5
main-->6
i:0
i:1
i:2
i:3
i:4
i:5
i:6
main-->7
main-->8
线程终止
i:7
方法四、使用Interrupt
当其他线程通过调用当前线程的interrupt方法,表示向当前线程打个招呼,告诉它可以中断线程的执行了,至于什么时候中断,取决于当前线程自己。
Thread.interrupted()对设置中断标识的线程复位,并返回当前的中断状态。
写个小demo看看:
public class TerminateThread {
private static int i;
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(() -> {
while (true) {
if (Thread.currentThread().isInterrupted()) {
System.out.println("before:" + Thread.currentThread().isInterrupted());
Thread.interrupted();//对中断标识复位
System.out.println("after:" + Thread.currentThread().isInterrupted());
}
}
});
thread.start();
TimeUnit.SECONDS.sleep(1);
thread.interrupt();//中断
}
}
输出:
before:true
after:false
使用interrupt方法终止线程有两种情况:
- 线程处于阻塞状态。例如,在使用sleep、调用锁的wait或者调用socket的receiver、accept方法时,会使线程处于阻塞状态。在调用线程的interrupt方法时,会抛出InterruptException异常,然后通过break跳出状态检测循环,可以有机会结束这个线程的执行。通常会以为只要调用interrupt方法就会结束线程,这是不对的,一定要先捕获InterruptException异常再通过break跳出循环,才能正常结束run方法。
public class TerminateThread {
private static int i;
public static void main(String[] args) {
Thread thread = new Thread(() -> {
//线程处于阻塞状态下,中断是有效的
try {
Thread.sleep(100000);
} catch (InterruptedException e) {
//抛出异常来响应中断请求
e.printStackTrace();
}
});
thread.start();
thread.interrupt();
}
}
- 线程未处于阻塞状态。此时,使用isInterrupted方法判断线程的中断标志来退出循环。在调用interrupt方法时,中断标志会被设置为true,并不能立刻退出线程,而是执行线程终止前的资源释放操作,等待资源释放完毕后退出该线程。
public class TerminateThread {
private static int i;
public static void main(String[] args) {
Thread thread = new Thread(() -> {
//Thread.currentThread().isInterrupted()默认是false
while (!Thread.currentThread().isInterrupted())//判断中断标识
i++;
});
thread.start();
//interrupt这个属性由false变成true
thread.interrupt();
}
}