1.stop()方法退出线程
线程退出有多种方法,我们先来演示线程.stop()方法,此方法用于强制结束一个线程
threadObj.stop();
我们现在来看一下示例代码:
public class ThreadTest {
public static void main(String[] args) {
Thread thread = new Thread( () -> {
int i = 0,j=0;
try {
while(true) {
i++;
System.err.println("i:"+i);
Thread.sleep(100);
j++;
System.err.println("j:"+j);
}
}catch(Exception ex)
{
ex.printStackTrace();
}
});
thread.start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
thread.stop();
}
}
上面方法分别使变量i和变量j分别间隔100毫秒后自增,并且输出对应的值,可以看到,现成正常退出!
但是我们翻看代码可以发现,stop()方法已经被标为过时,并不推荐使用,因为stop()方法是强制退出线程,并不保证所有必要逻辑执行完全,容易出现不可预料的错误:上方图片可以看到,i++后,j并未自增,而此时线程已经停止,这如果是在业务代码中,就容易导致不可预料的后果!
2.interrupt()方法标记退出线程
既然强制退出线程容易导致安全问题,那么我们就需要另一种新的方法,在需要线程需要退出时加上标记,然后用自己的逻辑手动的退出线程。
threadObj.interrupt();//将当前线程标记为退出状态
Thread.currentThread().isInterrupted()//判断当前线程是否已在停止状态
注意:调用此方法后并不会立即停止线程,此方法只是将此线程标记为退出状态,需要配合手动判断退出线程!
public class ThreadTest {
public static void main(String[] args) {
Thread thread = new Thread( () -> {
int i = 0,j=0;
try {
while(true) {
i++;
System.err.println("i:"+i);
j++;
System.err.println("j:"+j);
if(Thread.currentThread().isInterrupted())
{
System.err.println("自定义退出逻辑");
break;
}
}
}catch(Exception ex)
{
ex.printStackTrace();
}
});
thread.start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
thread.interrupt();
}
}
可以看到,这里就可以在所有业务执行完后安全的退出线程。
3.如何处理java.lang.InterruptedException
如果我们在上方代码中,添加了Thread.sleep()方法,就会发现如下异常:
这是因为线程在休眠时,被设置为中断状态,所以触发了此异常,并且将线程中断状态设置为False。所以一定要在此处加上异常处理逻辑,确保线程安全退出。
while (true) {
i++;
System.err.println("i:" + i);
try {
Thread.sleep(100);
} catch (Exception ex) {
ex.printStackTrace();
}
j++;
System.err.println("j:" + j);
System.err.println(Thread.currentThread().isInterrupted());
}
这就导致线程可以正常执行,并且之后的isInterrupted()退出线程方法不生效。
那么如何正确的面对此异常呢?
- 在Catch中直接退出线程
while (true) {
i++;
System.err.println("i:" + i);
try {
Thread.sleep(100);
} catch (Exception ex) {
break;
}
j++;
System.err.println("j:" + j);
System.err.println(Thread.currentThread().isInterrupted());
}
- 在Catch中将中断状态重新置位true
注意:此时线程并未停止,仍需手动退出线程
while (true) {
i++;
System.err.println("i:" + i);
try {
Thread.sleep(100);
} catch (Exception ex) {
Thread.currentThread().interrupt();
}
j++;
System.err.println("j:" + j);
if(Thread.currentThread().isInterrupted())
{
break;
}
}
- 捕获后不处理(极度不推荐)
如果此时捕获后不做任何处理的话,因为异常之后,此线程的中断状态会被重新置为false,所以并不会被下方的isInterrupted()方法捕获并退出,所以不推荐使用。
while (true) {
i++;
System.err.println("i:" + i);
try {
Thread.sleep(100);
} catch (Exception ex) {
}
j++;
System.err.println("j:" + j);
if(Thread.currentThread().isInterrupted())
{
break;
}
}
总的来说,如果可以避免,不使用线程休眠的方法,如果使用,则需要在保证逻辑安全的前提下使用,并正确的处理异常,退出线程!