停止一个线程的方法
1. interrupt 方法中断线程
- interrupt()方法调用之后只是在当前线程中打了一个停止标记,而不是真正的停止线程
- 需要结合isInterrupted()方法来判断是否被中断
- interrupted()判断是否被中断,并会清除当前的中断状态
后两个方法都属于Native方法
简单地讲,一个Native Method就是一个java调用非java代码的接口。一个Native Method是这样一个java的方法:该方法的实现由非java语言实现
中断线程可以通过以下几种方法
- 在线程内部抛出异常
通过在run方法中判断当前对象的interrupted()状态,如果是中断状态则抛出异常到达中断效果
public class MyThread extends Thread {
@Override
public void run() {
try {
for (int i = 0; i < 500000; i++) {
if (MyThread.interrupted()){
System.out.println("已经是停止状态了,我要退出了!");
throw new InterruptedException();
}
System.out.println("i = " + (i+1));
}
System.out.println("如果我被输出了,则代表线程没有停止");
} catch (InterruptedException e) {
System.out.println("在MyThread类中的run方法中被捕获");
e.printStackTrace();
}
}
public static void main(String[] args) {
try {
MyThread myThread = new MyThread();
myThread.start();
Thread.sleep(100);
myThread.interrupt();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("end!");
}
通过检查标志位来到达线程的中断
@Override
public void run() {
super.run();
for(int i = 0; i <= 200000; i++)
{ //判断是否被中断
if(Thread.currentThread().isInterrupted())
{
//处理中断逻辑
break;
}
System.out.println("i=" + i);
}
}
- 在线程sleep时,调用interrupt方法
先将线程sleep,再调用interrupt标记中断状态,interrupt会将处于阻塞状态下的线程中断并抛出InterruptedException,从而到达停止线程的效果
public class MyThread1 extends Thread {
@Override
public void run() {
try {
for (int i = 0; i < 100000; i++) {
System.out.println("i = " + (i+1));
}
System.out.println("run begin");
//interrupt是做一个中断标记,当时不会去中断正在运行的线程,当该线程处于阻塞状态时就会进行中断
//因此,先进行interrupt后,再遇到sleep阻塞时,才会进行中断
Thread.sleep(200000);
System.out.println("run end");
} catch (InterruptedException e) {
System.out.println("先停止,再遇到了sleep! 进入catch!");
e.printStackTrace();
}
}
public static void main(String[] args) {
MyThread1 myThread1 = new MyThread1();
myThread1.start();
myThread1.interrupt();
System.out.println("end!");
}
}
- 在线程内部使用return结束线程
调用interrupt标记为中断状态后,在run方法中判断当前线程状态,如果为中断状态则return,能达到停止线程的效果。
Thread.sleep()方法由于中断而抛出的异常,是会被清除中断标记的
2. 使用退出标记
- 通过设置volatile共享变量来终止,run()方法执行完毕,线程正常退出
- 将变量放在线程的循环中,做为循环的判断条件,通过改变boolean来终止线程
设置volatile的共享变量初始值为false,因为共享变量全局可用,所以可以将改变共享变量值的代码用一个方法来封装,在线程需要终止时,调用改变Boolean值的函数,从而终止线程
public class VolaThread extends Thread{
protected volatile boolean done = false;
public void run()
{
while (!done)
{
System.out.println("StopBoolean running");
try
{
sleep(720);
}
catch (InterruptedException e)
{
return;
}
}
System.out.println("StopBoolean finished");
}
public void shutDown()
{
done = true;
}
public static void main(String[] args) throws InterruptedException {
VolaThread t1 = new VolaThread();
t1.start();
Thread.sleep(1000 * 5);
t1.shutDown();
}
}
3. Stop()方法
-
线程调用stop()方法会被暴力停止,会产生不好的后果
- 强制性的停止线程会使一些工作不能完成
- 对锁定的对象进行了锁的释放,导致数据得不到同步的处理,出现数据的不一致性。
-
该方法已经被弃用