一、中断线程
当 run() 方法完成时,线程会自动销毁。但是可能需要在线程完成其生命周期之前杀死/停止线程。以前,方法suspend()、resume()和stop()用于管理线程的执行。但是这些方法在Java中被弃用了,因为它们可能导致系统崩溃。
挂起/停止线程的方法是使用布尔标志和Thread.interrupt()方法。
1、使用布尔标志
创建一个实现Runnable接口的类,其中类内有Boolean的标志,以及stop方法。
class MyThread implements Runnable {
// to stop the thread
private boolean exit;
private String name;
Thread t;
MyThread(String threadname)
{
name = threadname;
t = new Thread(this, name);
System.out.println("New thread: " + t);
exit = false;
t.start(); // Starting the thread
}
// execution of thread starts from run() method
public void run()
{
int i = 0;
while (!exit) {
System.out.println(name + ": " + i);
i++;
try {
Thread.sleep(100);
}
catch (InterruptedException e) {
System.out.println("Caught:" + e);
}
}
System.out.println(name + " Stopped.");
}
// for stopping the thread
public void stop()
{
exit = true;
}
}
// Main class
public class Main {
public static void main(String args[])
{
// creating two objects t1 & t2 of MyThread
MyThread t1 = new MyThread("First thread");
MyThread t2 = new MyThread("Second thread");
try {
Thread.sleep(500);
t1.stop(); // stopping thread t1
t2.stop(); // stopping thread t2
Thread.sleep(500);
}
catch (InterruptedException e) {
System.out.println("Caught:" + e);
}
System.out.println("Exiting the main Thread");
}
}
2、使用原子布尔标志
创建一个实现Runnable接口的类,其中类内有AtomicBoolean的标志,以及stop方法。
package com.algorithm.demo.thread;
import java.util.concurrent.atomic.AtomicBoolean;
public class MyThreadDemo implements Runnable
{
// to stop the thread
private final AtomicBoolean running = new AtomicBoolean(false);
private String name;
Thread t;
public MyThreadDemo(String threadname)
{
name = threadname;
t = new Thread(this, name);
System.out.println("New thread: " + t);
t.start(); // Starting the thread
}
// execution of thread starts from run() method
public void run()
{
running.set(true);
int i = 0;
while (!running.get()) {
System.out.println(name + ": " + i);
i++;
try {
Thread.sleep(100);
}
catch (InterruptedException e) {
System.out.println("Caught:" + e);
}
}
System.out.println(name + " Stopped.");
}
public void stop() {
running.set(false);
}
}
调用并创建线程,并调用stop改变AtomicBoolean的值。
@Test
void thread_stop_with_bool()
{
// creating two objects t1 & t2 of MyThread
MyThreadDemo t1 = new MyThreadDemo("First thread");
MyThreadDemo t2 = new MyThreadDemo("Second thread");
try {
Thread.sleep(500);
t1.stop(); // stopping thread t1
t2.stop(); // stopping thread t2
Thread.sleep(500);
}
catch (InterruptedException e) {
System.out.println("Caught:" + e);
}
System.out.println("Exiting the main Thread");
}
2、使用 Thread.interrupt() 方法
当对一个线程,调用其interrupt()方法时。
1、 如果线程处于被阻塞状态(例如处于sleep, wait, join 等状态),那么线程将立即退出被阻塞状态,并抛出一个InterruptedException异常。
2、如果线程处于正常活动状态,那么会将该线程的中断标志设置为 true。被设置中断标志的线程将继续正常运行,不受影响。
在调用阻塞方法时正确处理InterruptedException异常,catch后就会结束线程。
package com.algorithm.demo.thread;
import java.util.concurrent.atomic.AtomicBoolean;
public class ControlSubThread implements Runnable {
private Thread worker;
private AtomicBoolean running = new AtomicBoolean(false);
private AtomicBoolean stopped = new AtomicBoolean(false);
private int interval = 50000;
// ...
public void interrupt() {
running.set(false);
worker.interrupt();
}
public void start() {
worker = new Thread(this);
worker.start();
}
boolean isRunning() {
return running.get();
}
boolean isStopped() {
return stopped.get();
}
public void run() {
running.set(true);
stopped.set(false);
while (running.get()) {
try {
Thread.sleep(interval);
} catch (InterruptedException e){
Thread.currentThread().interrupt();
System.out.println(
"Thread was interrupted, Failed to complete operation");
}
// do something
}
stopped.set(true);
}
}
3、总结
如果想要中断一个线程。
1、如果中断标志位不会被多个线程使用,则可以使用boolean标志位,否则使用AtomicBoolean标志位(根据情况考虑是否使用静态)。
2、在正常运行任务时,经常检查本线程的中断标志位,如果被设置了中断标志就自行停止线程。
3、在调用阻塞方法时正确处理InterruptedException异常。(catch异常后就结束线程。)