java如何及时的停止运行的线程

 

背景:公司抽奖,java写的抽奖程序,待领导喊完开始后,疯狂输出,一段时间后,领导喊 "停......" ,台下一阵哄笑,画面异常尴尬。

   过时危险的方法不再今天讨论之内,读者自行补充即可( Thread.stop, Thread.suspend, Thread.resume 和Runtime.runFinalizersOnExit).

停止线程的方法有四种:

  1  基于用户自定义的状态字段

   2 基于线程的中断机制(并不是只要发了中断请求,运行线程就会第一时间停止,中断机制是一种协程,类似求人办事

   3 前两种相结合

   4 最终方案

 

1  基于用户自定义的状态字段

 实现方式: 1>自定义boolean性的字段,记住最好用volatile修改,保证可见性

                     2>对外提供实例方法,用于修改修改状态字段

                     3>判断状态(不限于while ,if......),符合条件,结束程序

  缺点:对于简单的业务代码适用,稍微复杂的场景就不行了,基本上没用武之地

public class InterrputedTest {

	public static void main(String[] args) {
		MainTask mainTask = new MainTask();
		Thread t = new Thread(mainTask);
		t.start();
		try {
			TimeUnit.SECONDS.sleep(10);
			mainTask.setStop();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}
}

class MainTask implements Runnable {
	private volatile boolean run = true;

	public void run() {
		while (run) {
			System.out.println("正在运行");
		}
	}

	public void setStop() {
		run = false;
	}

}

2  基于线程的中断机制

 实现方式: 1>在工作线程中响应中断异常,切记不要自己吃掉异常

                     2>外部调用实例线程的interrupt()方法,设置中断状态

                     3>判断状态(不限于while ,if......),符合条件Thread.currentThread().isInterrupted()或者Thread.interrupted(),结束程序(两种方法的区别是:isInterrupted()单纯的判断线程的中断状态,静态方法interrupted()不但返回当前状态并且会重新初始化为false)

  缺点:只适用于响应中断异常(InterruptedException)的程序,不能中断其他异常程序。

public class InterrputedTest {

	public static void main(String[] args) {
		MainTask mainTask = new MainTask();
		Thread t = new Thread(mainTask);
		t.start();
		try {
			TimeUnit.SECONDS.sleep(10);
			t.interrupt();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}
}

class MainTask implements Runnable {
	public void run() {
		while (Thread.interrupted()) {
			try {
				TimeUnit.SECONDS.sleep(10);
				System.out.println("正在运行");
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				break;
			}
		}
	}
}

 

3 前两种相结合

实现方式:结合前两种方案

 缺点:不能中断其他异常程序,例如IO线程,socket线程等。

public class InterrputedTest {

	public static void main(String[] args) {
		MainTask mainTask = new MainTask();
		Thread t = new Thread(mainTask);
		t.start();
		try {
			TimeUnit.SECONDS.sleep(10);
			t.interrupt();
			mainTask.stop();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}
}

class MainTask implements Runnable {
	private volatile boolean run=true;
	public void run() {
		while (run && !Thread.interrupted()) {
			try {
				TimeUnit.SECONDS.sleep(10);
				System.out.println("正在运行");
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				break;
			}
		}
	}
	public void stop(){
		this.run=false;
	}
}

 4 最终方案

如果想要完美的快速的停止一个线程,前三种方案并不能达到目的,再采用第三种方案的前提下,我们需要思考几个问题。

1> 任务是否可以拆分?如果可以拆分利用循环多次监测,每次循环判断条件,加快停止的时间。

2>对于不能再拆分的耗时任务怎么处理?能响应中断请求的利用中断异常,不能响应中断异常的阻塞,需要特定处理,例如IO操作可以关闭流,让其抛出异常结束,socket需要关闭流,让其抛出异常结束。(这一类针对能抛出异常的处理方案)

3>阻塞的代码的可以参考第二条,非阻塞的代码,怎么弄,例如占用cpu的耗时操作,排序?可以通过多处增加状态的判断(本方案使用于不能抛出异常的处理方案,运行效率和响应速度需要作出权衡)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值