如何停止一個正在運行的線程? 這個一個面試常問的問題, 我們有兩種辦法, 分別是stop()和interrupt(), 但stop()太過於暴力, 無法保證線程業務的原子性, 且已過期, 不推薦使用.
使用stop()來停止線程
stop()方法讓線程立即停止運行, 這種暴力停止可能會破壞線程業務的原子性, 如下所示:
static class MyThread extends Thread {
@Override
public void run() {
while (true) {
System.out.println("線程開始執行...");
System.out.println("業務步驟1");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("業務步驟2");
System.out.println("線程執行完畢...");
}
}
}
public static void main(String[] args) {
MyThread thread = new MyThread();
thread.start();
try {
Thread.sleep(2000);
thread.stop();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
執行結果爲:
線程開始執行...
業務步驟1
使用interrupt() + return來停止線程
線程調用interrupt()會生成一箇中斷標記, 在線程邏輯中通過isInterrupted()判斷是否存在中斷標記, 存在則return.
static class MyThread extends Thread {
@Override
public void run() {
for (int i = 0; i < 500000; i++) {
if (this.isInterrupted()) {
System.out.println("線程終止, 停止for循環.");
return;
}
System.out.println("i=" + (i + 1));
}
}
}
public static void main(String[] args) {
MyThread thread = new MyThread();
thread.start();
try {
Thread.sleep(200);
thread.interrupt();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
結果:
…
i=38319
i=38320
i=38321
線程終止, 停止for循環.
使用interrupt() + InterruptedException來停止線程
線程調用interrupt()會生成一箇中斷標記, 在線程邏輯中通過isInterrupted()判斷是否存在中斷標記, 存在則拋出一個InterruptedException, 同時捕獲它.
static class MyThread extends Thread {
@Override
public void run() {
try {
for (int i = 0; i < 100000; i++) {
if (this.isInterrupted()) {
System.out.println("線程終止, 停止for循環.");
throw new InterruptedException();
}
System.out.println("i=" + (i + 1));
}
} catch (InterruptedException e) {
System.out.println("MyThread拋出InterruptedException.");
e.printStackTrace();
}
}
}
public static void main(String[] args) {
MyThread thread = new MyThread();
thread.start();
try {
Thread.sleep(200);
thread.interrupt();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
結果:
i=34901
i=34902
i=34903
線程終止, 停止for循環.
MyThread拋出InterruptedException.
java.lang.InterruptedException
at org.tyshawn.thread.ThreadTest$MyThread.run(ThreadTest.java:27)
interrupt()遇到sleep(), join()和wait()會拋出一個InterruptedException
當線程是阻塞狀態時, 這時調用interrupt()方法會拋出一個InterruptedException.
static class MyThread extends Thread {
@Override
public void run() {
try {
System.out.println("線程開始執行");
Thread.sleep(300);
//this.join();
//this.wait();
System.out.println("線程執行完畢");
} catch (InterruptedException e) {
System.out.println("MyThread拋出InterruptedException.");
e.printStackTrace();
}
}
}
public static void main(String[] args) {
MyThread thread = new MyThread();
thread.start();
try {
Thread.sleep(200);
thread.interrupt();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
結果:
線程開始執行
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at org.tyshawn.thread.ThreadTest$MyThread.run(ThreadTest.java:56)
MyThread拋出InterruptedException.