在介绍停止线程的方法前,先介绍几个方法作为预备知识:
1、interrupt()
这个方法的作用是使得调用该方法的线程的interrupted状态为true。注意,这个方法并不是直接停止线程,它只是修改线程的interrupted状态位,相当于给该线程打了个“需要停止”的标记。我们可以通过实验来验证这一现象:
public class Test2 {
public void print() {
for (int i = 0; i < 500000; i++) {
System.out.println("i=" + i);
if (Thread.currentThread().isInterrupted()) {
System.out.println("被interrupt了:" + Thread.currentThread().isInterrupted());
}
}
}
public static void main(String[] args) throws InterruptedException {
Test2 test2 = new Test2();
Thread t1 = new Thread(() -> {
test2.print();
}, "t1");
t1.start();
Thread.sleep(500);
t1.interrupt();
}
}
执行结果:
可以看到,虽然线程t1的interrupted状态早已为true,但是循环还是会继续下去,线程t1并未停止
2、interrupted()
这个方法的作用是返回当前线程的interrupted状态,“当前线程”指的是当前正在运行的线程。这个方法是static方法,推荐用Thread.interrupted()方式来调用。注意,调用该方法的线程,它的interrupted状态会被重置为false,即在某个线程调用interrupt()后,第一次调用Thread.interrupted()返回为True,然后什么都不做立即第二次调用Thread.interrupted(),返回的将会是False。我们可以从源码中验证这一点:
3、isInterrupted()
这个方法的作用是返回调用该方法的线程的interrupted状态。要注意和interrupted()方法进行区分。调用该方法的线程,不一定是当前正在运行的线程。比如有两个线程t1和t2,此时t2正在运行,然后t2的逻辑中有一步是t1.isInterrupted(),这一步返回的是线程t1的interrupted状态,而不是正在运行的t2的interrupted状态。而且这个方法并不会重置调用该方法的线程的interrupted状态,我们可以从源码中验证这一点:
接下来介绍停止线程的方法
1、抛出异常法:
具体方法就是在线程run()方法内部用try/catch将整个run方法内部代码括起来,加上该线程的interrupted状态判断,若为true,则抛出异常,此时线程会停止。
public class Test2 {
public static void main(String[] args) throws Exception {
Thread thread = new Thread(new MyThread(), "t1");
thread.start();
Thread.sleep(500);
thread.interrupt();
}
}
class MyThread implements Runnable {
@Override
public void run() {
try {
for (int i = 0; i < 500000; i++) {
System.out.println("i=" + i);
if (Thread.interrupted()) {
System.out.println("线程要停止了...");
throw new InterruptedException();
}
}
} catch (InterruptedException e) {
System.out.println("进入catch");
} finally {
System.out.println("线程停止时的收尾处理。。。");
}
}
}
执行结果:
2、return停止法:
在run()方法内部加上该线程的interrupted状态判断,若为true,则可以用return直接退出run()方法。
public class Test2 {
public static void main(String[] args) throws Exception {
Thread thread = new Thread(new MyThread(), "t1");
thread.start();
Thread.sleep(500);
thread.interrupt();
}
}
class MyThread implements Runnable {
@Override
public void run() {
for (int i = 0; i < 500000; i++) {
System.out.println("i=" + i);
if (Thread.interrupted()) {
System.out.println("线程要停止了...");
System.out.println("收尾工作...");
return;
}
}
}
}
执行结果:
3、用stop()方法停止(不推荐,而且该方法已过时):
调用stop()方法的线程会立即停止,无法在线程停止前进行一些收尾工作,比如该线程的一个事务还未执行完,此时该线程被stop了,我们是无法将这个事务回滚的,这样就造成了数据不一致的问题。
public class Test {
private String user = "u1";
private String pwd = "p1";
public synchronized String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
public synchronized String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
public synchronized void print(String user, String pwd) throws InterruptedException {
this.user = user;
Thread.sleep(1000);
this.pwd = pwd;
}
public static void main(String[] args) throws InterruptedException {
Test test = new Test();
Thread thread = new Thread(() -> {
try {
test.print("u2", "p2");
} catch (InterruptedException e) {
e.printStackTrace();
}
});
thread.start();
Thread.sleep(500);
thread.stop();
System.out.println(test.getUser() + "===" + test.getPwd());
}
}