java线程挂掉_java线程之停止线程

在Java中有以下3种方法可以终止一个正在运行的线程:

1、使用退出标志,是线程正常退出,也就是run方法完成后线程终止。

2、使用stop方法强制终止线程,但不推荐使用这个方法,因为stop、suspend和resume一样,都是作废过期的方法。

3、使用interrupt方法中断线程,大多数停止一个线程使用Thread.interrupt()方法,但是这个方法不会终止一个正在运行的线程,还需要加入一些判断才可以完成线程的停止。

下面我就用几个例子来介绍一下各种停止线程的效果。 一、停不了的线程——interrupt本例子将调用interrupt()方法来停止线程,但是效果并不理想,并不能停止正在运行的线程,因为调用interrupt()方法仅仅是在当前线程中打了一个停止的标记,并不能真的停止线程。

public static void main(String[] args) {

MyThread1 t = new MyThread1();

t.start();

try {

Thread.sleep(2);

t.interrupted();

} catch (InterruptedException e) {

System.out.println("main catch");

e.printStackTrace();

}

}

public static class MyThread1 extends Thread {

@Override

public void run() {

super.run();

for (int i = 0; i < 5000; i++) {

System.out.println("i=" + (i + 1));

}

}

}

运行结果我值截取了最后一段,控制台上正好输出到5000,说明调用interrupt方法并没有停止线程,运行结果如下:

6baa4ac15f10fdf1fc6daea455a3b3f0.png

那么怎么才能停止线程呢?下面我回来介绍。

二、能停止的线程——异常法

先看一个例子:

public static void main(String[] args) throws InterruptedException {

MyThread t = new MyThread();

t.start();

Thread.sleep(50);

t.interrupt();

System.out.println("end");

}

public static class MyThread extends Thread {

@Override

public void run() {

// TODO Auto-generated method stub

super.run();

for (int i = 0; i < 5000; i++) {

if (this.interrupted()) {

System.out.println("已经是停止状态了!我要退出了!");

break;

}

System.out.println("i=" + (i + 1));

}

System.out.println("如果我被输出了,说明run方法还在继续执行,线程并未停止!");

}

}

输出结果如下:

dfb17d70b25cd999f283473a2e53d4ad.png

从上面的结果可以看出来,这样写只是把for循环结束了,但是下面接着输出了“如果我被输出了,说明run方法还在继续执行,线程并未停止!”这句话,说明这样写并不能让run方法停止,所以这样写不可行。下面再来看一个例子。

public static void main(String[] args) throws InterruptedException {

MyThread t = new MyThread();

t.start();

Thread.sleep(50);

t.interrupt();

System.out.println("end");

}

public static class MyThread extends Thread {

@Override

public void run() {

super.run();

try {

for (int i = 0; i < 5000; i++) {

if (this.interrupted()) {

System.out.println("已经是停止状态了!我要退出了!");

//异常法结束线程

throw new InterruptedException();

}

System.out.println("i=" + (i + 1));

}

System.out.println("我在for下面");

} catch (InterruptedException e) {

System.out.println("进入Thread线程的run方法中的catch!");

e.printStackTrace();

}

}

}

下面来看一下控制台上的输出结果:

5250ac1d687e257b89c6f573513e783a.png

来分析一下结果,throw new InterruptedException()这句话下面的内容已经不会再执行了,因为“我在for下面”这句话并没有输出来,而是进入了catch,结束了整个run方法。所以异常方法来停止线程方法是靠谱的。

三、在沉睡中停止线程

public static void main(String[] args) {

try {

MyThread t = new MyThread();

t.start();

Thread.sleep(200);

t.interrupt();

} catch (Exception e) {

System.out.println("main catch");

e.printStackTrace();

}

System.out.println("end!");

}

public static class MyThread extends Thread {

@Override

public void run() {

super.run();

try {

System.out.println("run begin");

//为了确保能停止线程,这个休眠时间尽量长一点,如果时间太短,有可能主线程还没休眠结束呢,子线程就休眠结束了,这个线程也就正常运行了。

sleep(2000);

System.out.println("run end");

} catch (Exception e) {

System.out.println("在沉睡中被停止!进去catch!" + this.isInterrupted());

e.printStackTrace();

}

}

}

运行结果如下:

77bf30abcd6173b1231e60eefb61ca9e.png

来分析一下结果,"run end"这句话没有输出,说明子线程里的sleep下面的内容再也不会执行了,而是进入到catch里面了,从而停止了run方法。说明这样写也是靠谱的。

四、能停止的线程——暴力停止

使用stop()方法停止线程是非常暴力的行为,并且使用stop()方法会导致运行结果不一样,已经被官方文档废弃使用了。不使用的原因是不安全,假如当执行到stop方法时,子线程正在执行 synchronized里边的内容,那么不管

synchronized的方法有没有执行完,都会立刻停止这个线程,造成线程不安全。下面我来展示一个例子。

public static void main(String[] args) {

MyThread t = new MyThread();

t.start();

try {

Thread.sleep(9000);

t.stop();

} catch (Exception e) {

e.printStackTrace();

}

}

public static class MyThread extends Thread {

private int i = 0;

@Override

public void run() {

super.run();

while (true) {

i++;

System.out.println("i=" + i);

try {

sleep(1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}

五、使用return停止线程

将interrupt()和return结合也能实现停止线程的效果。但是建议使用抛异常停止线程,因为可以处理发生异常时候的相关信息。下面看一段代码。

public static void main(String[] args) throws InterruptedException {

MyThread t = new MyThread();

t.start();

Thread.sleep(2);

t.interrupt();

}

public static class MyThread extends Thread {

@Override

public void run() {

super.run();

for (int i = 0; i < 5000; i++) {

if (this.interrupted()) {

System.out.println("已经是停止状态了!我要退出了!");

return;

}

System.out.println("i=" + (i + 1));

}

}

}

下面看一下运行结果:

6518c4175dc1e8f1953d80b7725ec122.png

六、暂停线程

暂停线程异味着此线程还可以恢复运行,在java中使用suspend()方法暂停线程,使用resume()方法恢复线程。不推荐suspend()和resume()方法,是因为容易造成死锁,比如执行suspend()这个方法的线程持有一个重要资源的锁,那么在没有执行恢复方法之前,是不会释放掉这个锁的,但是这个时候有另一个线程执行了resume()方法,但是这个线程恢复以后要想继续执行下去需要那个重要资源的锁,这个时候两个线程就造成死锁了

使用下面看一段代码。

public static void main(String[] args) throws InterruptedException {

MyThread t = new MyThread();

t.start();

//A段 暂停线程

t.suspend();

System.out.println("A="+System.currentTimeMillis() +"\t"+"i="+t.getI());

Thread.sleep(500);

System.out.println("A="+System.currentTimeMillis() +"\t"+"i="+t.getI());

//B段 继续恢复

t.resume();

System.out.println("B="+System.currentTimeMillis() +"\t"+"i="+t.getI());

Thread.sleep(500);

System.out.println("B="+System.currentTimeMillis() +"\t"+"i="+t.getI());

//C段 暂停线程

t.suspend();

System.out.println("C="+System.currentTimeMillis() +"\t"+"i="+t.getI());

Thread.sleep(500);

System.out.println("C="+System.currentTimeMillis() + "\t"+"i="+t.getI());

}

public static class MyThread extends Thread {

private long i = 0;

public long getI(){

return i;

}

public void setI(long i){

this.i=i;

}

@Override

public void run() {

super.run();

while (true) {

i++;

}

}

}

下面来分析一下运行结果:在A段中,先执行的是suspend()暂停线程的方法,所以从结果可以看出,系统的当前时间在变,但是i值确一直是0,说明线程没有在执行,仍是初始化的值,到了B段,执行了resume()恢复线程的方法,从结果也可以看出,当前系统的时间在变,i值也在改变,说面线程已经被恢复并在执行了,到了C段,出现这样的结果和A段原因是一样的。

365b7c1dd75926db584b7e178cf72bd8.png

以上我说了很多小例子,如果亲手敲一遍代码,看一下执行结果,会有更好的理解,毕竟线程执行的结果不是单一的。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值