Java多线程-停止线程

停止线程是在多线程开发时很重要的技术点,掌握此技术可以对线程的停止进行有效的处理。停止线程在Java语言中不像break那么干脆,需要一些技巧性的处理。使用Java内置支持多线程的类设计多线程应用是很常见的事情,然而,多线程给开发人员带来了一些新的挑战,如果处理不好就会导致超出预期的行为并且难以定位错误。停止一个线程意味着在线程处理完任务之前停掉正在做的操作,也就是放弃当前的操作。虽然这看起来很简单,但是必须做好防范措施,以便达到预期的效果。停止一个线程可以使用Thread.stop()方法,但是这个方法是不安全的(unsafe),并且是已被弃用作废的(deprecated),在将来的Java版本中,这个方法将不可用或不被支持。

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

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

2、使用stop方法强行终止线程,但是不推荐使用此方法,因为stop和suspend及resume一样,都是作废过期的方法,使用它们可能产生不可预料的结果

3、使用interrupt方法中断线程。


举例:使用interrupt()方法来停止线程,但interrupt()方法的使用效果并不像for+break语句那样,马上就停止循环。调用interrupt()方法仅仅是在当前线程中打了一个停止的标记,并不是真的停止线程。

package com.js.stop;

public class MyThread extends Thread {
	@Override
	public void run(){
		super.run();
		for(int i = 0;i<500000;i++){
			System.out.println("i="+(i+1));
		}
	}
}

package com.js.stop;

public class Run {
	public static void main(String[] args){
		try {
			MyThread myThread = new MyThread();
			myThread.start();
			myThread.sleep(2000);
			myThread.interrupt();
		} catch (InterruptedException e) {
			System.out.println("main catch");
			e.printStackTrace();
		}
	}
}


从运行结果来看,调用interrupt方法并没有停止线程。那么,如何停止线程呢?

1、异常法

在线程中用for语句来判断一下线程是否是停滞状态,如果是,则后面的代码不再运行即可。

例如:

package com.js.demo2;

public class MyThread extends Thread{
	@Override
	public void run(){
		super.run();
		for(int i=0;i<500000;i++){
			if(this.interrupted()){
				System.out.println("已经是停止状态了!我要退出了!");
				break;
			}
			System.out.println("i="+(i+1));
		}
	}
}

package com.js.demo2;

public class Run {
	public static void main(String[] args){
		try {
			MyThread myThread = new MyThread();
			myThread.start();
			Thread.sleep(2000);
			myThread.interrupt();
		} catch (InterruptedException e) {
			System.out.println("main catch");
			e.printStackTrace();
		}
		System.out.println("end!");
	}
}

上面的示例虽然停止了线程,但如果for下面还有语句,还是会继续运行的。例如:

package com.js.demo2;

public class MyThread extends Thread{
	@Override
	public void run(){
		super.run();
		for(int i=0;i<500000;i++){
			if(this.interrupted()){
				System.out.println("已经是停止状态了!我要退出了!");
				break;
			}
			System.out.println("i="+(i+1));
		}
		System.out.println("我被输出,如果此代码是for又继续运行,线程并未停止!");
	}
}

该如何解决语句继续执行的问题呢?

继续更新代码:

package com.js.demo2;

public class MyThread extends Thread{
	@Override
	public void run(){
		super.run();
		try {
			for(int i=0;i<500000;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("进入MyThread.java类run方法中得catch了!");
			e.printStackTrace();
		}
	}
}

package com.js.demo2;

public class Run {
	public static void main(String[] args){
		try {
			MyThread myThread = new MyThread();
			myThread.start();
			Thread.sleep(2000);
			myThread.interrupt();
		} catch (InterruptedException e) {
			System.out.println("main catch");
			e.printStackTrace();
		}
		System.out.println("end!");
	}
}


2、在沉睡中停止

如果线程在sleep()状态下停止线程,会是什么效果呢?

例如:

package com.js.demo3;

public class MyThread extends Thread {
	@Override
	public void run(){
		super.run();
		try {
			System.out.println("run begin");
			Thread.sleep(200000);
			System.out.println("run end");
		} catch (InterruptedException e) {
			System.out.println("在沉睡中被停止!进入catch!"+this.isInterrupted());
			e.printStackTrace();
		}
	}
}

package com.js.demo3;

public class Run {
	public static void main(String[] args){
		try {
			MyThread myThread = new  MyThread();
			myThread.start();
			Thread.sleep(200);
			myThread.interrupt();
		} catch (InterruptedException e) {
			System.out.println("main catch");
			e.printStackTrace();
		}
	}
}

运行结果:

run begin
在沉睡中被停止!进入catch!false
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at com.js.demo3.MyThread.run(MyThread.java:9)

从结果来看,如果在sleep状态下停止某一线程,会进入catch语句,并且清楚停止状态值,使之变成false。

前一个实验是先sleep,然后再用interrupt停止,与之相反的操作在学习线程时也要注意:

package com.js.demo3;

public class MyThread extends Thread {
	@Override
	public void run(){
		super.run();
		try {
			for(int i=0;i<100000;i++){
				System.out.println("i="+(i+1));
			}
			System.out.println("run begin");
			Thread.sleep(200000);
			System.out.println("run end");
		} catch (InterruptedException e) {
			System.out.println("先停止,再遇到了sleep!进入catch!");
			e.printStackTrace();
		}
	}
}

package com.js.demo3;

public class Run {
	public static void main(String[] args){
		MyThread myThread = new MyThread();
		myThread.start();
		myThread.interrupt();
		System.out.println("end!");
	}
}


3、使用return停止线程

讲方法interrupt()与return组合使用也能实现停止线程的效果

例如:

package com.js.demo4;

public class MyThread extends Thread {
	@Override
	public void run(){
		while(true){
			if(this.isInterrupted()){
				System.out.println("停止了!");
				return;
			}
			System.out.println("timer="+System.currentTimeMillis());
		}
	}
}

package com.js.demo4;

public class Run {

	public static void main(String[] args) throws InterruptedException {
		MyThread myThread = new MyThread();
		myThread.start();
		Thread.sleep(20000);
		myThread.interrupt();
	}

}


运行结果:

...

timer=1496394913416
timer=1496394913416
timer=1496394913416
timer=1496394913416
timer=1496394913416
timer=1496394913416
停止了!

不过还是建议使用“抛异常”的方法来实现线程的停止,因为catch块中还可以将异常向上抛,使线程停止的事件得以传播。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值