多线程的停止
前言
由于实现业务功能的需要,终于(?)可以再次使用多线程并发来解决效率功能的效率问题。
在实现对应功能时,需考虑到线程在执行业务处理的过程中,由外部对其发出停止命令的响应。
在此之前,个人就已经了解到可以在线程的实现处理类中加入一个标志符等之类的方法停止线程的处理。但这样的处理有多种局限性,且不能满足当前的业务需求。因此,再次学习、查找资料,总结了以下的多线程停止的方法
控制符
控制符,就是相对简单的在线程中加入一个成员变量,用于退出线程方法体。
样例代码如下:
public static void main(String[] args) throws Exception {
ThreadTest test = new ThreadTest();
MyRunnable run = test.new MyRunnable();
Thread t = new Thread(run);
t.start();
Thread.sleep(20);
run.stop();
}
class MyRunnable implements Runnable {
private volatile boolean stop = false;
public void stop() {
System.out.println("调用stop方法啦~");
this.stop = true;
}
@Override
public void run() {
try {
int count = 0;
while (!stop) {
count++;
Thread.sleep(20);
}
System.out.println("退出循环体啦~");
}catch (Exception e) {
e.printStackTrace();
}
}
}
当这个使用上方代码启动一个线程后,可以在外部持有对象的时候,调用方法 stop()
方法,退出线程。
需要注意的是,作为控制符的成员变量在声明时需要使用修饰符 volatile
,用以保持基本的读写顺序。
捕获 interrupt 异常
直接在线程类中增加一个控制符,可能有人觉得不够优雅(?),那么有没有java线程原生的退出线程方法呢?
答案是有的,可能有人想到了 Thread.stop()
方法,但这个已经被标记为了 Deprecated ,不推荐使用,并且也不能保证使用了Thread.stop()
方法之后,线程会真的退出。
java给出的替代 stop() 方法的方案是 Thread.interrupt()
。
大部分的线程方法体中,都使用了阻塞的方法,例如 sleep()
、wait()
等。此时,就可以使用线程Thread类的 Thread.interrupt()
方法,让这些阻塞方法抛出 InterruptiedException
。
样例代码如下:
class MyRunnable2 implements Runnable {
@Override
public void run() {
try {
System.out.println("进入run方法。。");
int count = 0;
while (true) {
count++;
// sleep会抛出 InterruptiedException
Thread.sleep(20);
}
} catch (InterruptedException e) {
System.out.println("InterruptiedException被捕获啦,退出循环体!");
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
运行的代码如下:
MyRunnable2 run2 = test.new MyRunnable2();
Thread t = new Thread(run2);
t.start();
Thread.sleep(20);
t.interrupt();
检查 Thread.isInterrupted()
那如果线程体内,没有调用阻塞的方法,Thread.interrupt()
方法调用后,就没有会抛出 InterruptiedException
的地方了。
这个时候,就需要在线程体内使用 Thread.isInterrupted()
方法,检查当前线程是否被 interrupt 了。
样例代码如下:
class MyRunnable3 implements Runnable {
@Override
public void run() {
try {
System.out.println("进入run方法。。");
int count = 0;
while (true) {
count++;
if(Thread.interrupted()){
System.out.println("线程被 interrupt 了!!");
break;
}
}
System.out.println("退出了循环体啦!");
}catch (Exception e) {
e.printStackTrace();
}
运行的代码如下:
MyRunnable3 run3 = test.new MyRunnable3();
Thread t = new Thread(run3);
t.start();
Thread.sleep(200);
t.interrupt();
源代码
public class ThreadTest {
public static void main(String[] args) throws Exception {
ThreadTest test = new ThreadTest();
MyRunnable run = test.new MyRunnable();
Thread t = new Thread(run);
t.start();
Thread.sleep(20);
run.stop();
MyRunnable2 run2 = test.new MyRunnable2();
t = new Thread(run2);
t.start();
Thread.sleep(200);
t.interrupt();
MyRunnable3 run3 = test.new MyRunnable3();
t = new Thread(run3);
t.start();
Thread.sleep(200);
t.interrupt();
}
class MyRunnable implements Runnable {
private volatile boolean stop = false;
public void stop() {
System.out.println("调用stop方法啦~");
this.stop = true;
}
@Override
public void run() {
try {
int count = 0;
while (!stop) {
count++;
Thread.sleep(20);
}
System.out.println("退出循环体啦~");
} catch (Exception e) {
e.printStackTrace();
}
}
}
class MyRunnable2 implements Runnable {
@Override
public void run() {
try {
System.out.println("进入run方法。。");
int count = 0;
while (true) {
count++;
// sleep会抛出 InterruptiedException
Thread.sleep(20);
}
} catch (InterruptedException e) {
System.out.println("InterruptiedException被捕获啦,退出循环体!");
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
class MyRunnable3 implements Runnable {
@Override
public void run() {
try {
System.out.println("进入run方法。。");
int count = 0;
while (true) {
count++;
if (Thread.interrupted()) {
System.out.println("线程被 interrupt 了!!");
break;
}
}
System.out.println("退出了循环体啦!");
} catch (Exception e) {
e.printStackTrace();
}
}
}
}