Thread之结束线程(8)

接上一篇:Thread的Interrupt()源代码分析(7)

在Thread中stop()方法已经被不推荐使用了,那么我们该如何去以一种优美的姿态去结束掉它呢?

首先,我们能否在线程里给一个标识,标识改变就结束掉它呢?请看最基础的结束线程的方式:

class ThreadDemo02 implements Runnable{
private boolean flag = true;
	@Override
	public void run() {
		while (flag){
			//停止线程---让run方法结束,改变运行标志也就意味着线程结束
			System.out.println(Thread.currentThread().getName()+"...run");
		}
	}
	public void changeFlag(){
		flag = false;
	}
}

public class StopThread {
	public static void main(String[] args) throws InterruptedException {
		ThreadDemo02 t = new ThreadDemo02();
		Thread t1 = new Thread(t);
		Thread t2 = new Thread(t);
		t1.start();
		t2.start();
		int num = 0;
		while (true){
			if(num++ == 6000){
				t.changeFlag();
				break;
			}
			num++;
			System.out.println(Thread.currentThread().getName()+"...停止..."+num);
		}

}

这个是比较简单的结束方式,但是会存在问题,当线程出于冻结状态就不会读取到标记,那么线程就不会结束。

接下来我们来看第二种实现方式,原理是线程在运行的时候会判断该线程是否为中断状态,如果不是,就往下执行,而且当线程为blocked状态时,使用interrupt()则会catch捕获到,然后也会结束线程。

class ThreadDemo06 implements Runnable{
	@Override
	public void run(){
		//停止线程---让run方法结束,改变运行标志也就意味着线程结束
		/*
		 * 特殊情况:当线程出于冻结状态就不会读取到标记,那么线程就不会结束
		 * 解决方案:把需要冻结的线程进行清除状态,强制让线程恢复到运行状态
		 * 然后改变操作标记让线程结束
		 * */
		try{
			while(!Thread.currentThread().isInterrupted()){
				System.out.println("_____________—————————_________");
				Thread.sleep(5000);
			}
			System.out.println("结束");
		}catch(Exception e){
			System.out.println("中断结束");
			System.out.println(e.getMessage());
		}
	}

}


public class StopThread {
	public static void main(String[] args) throws InterruptedException {
		
		ThreadDemo06 rt = new ThreadDemo06();
		Thread t = new Thread(rt);
		t.start();
		Thread.sleep(2_000);
		t.interrupt();
}

这里,当线程为阻塞状态了,确实会停止,但是,如果线程是在运行状态呢,怎么可以让它暴力停止呢?

我们来看网上流传的第三种方式。

 

class ThreadDemo07{
	private Thread executeThread;
	private boolean finished = false;

	public void execute(final Runnable tt) {
		executeThread = new Thread() {
				@Override
				public void run() {
				Thread runner = new Thread(tt);
//设置其为守护线程
				runner.setDaemon(true);

				runner.start();
				try {
//防止被守护线程执行时间短,轮不到守护线程执行任务
					runner.join();
//后面还有一句代码,如果守护线程未执行完并且未抛出InterruptedException,是不会执行到下面一句的
					finished = true;
				} catch (InterruptedException e) {
					System.out.println("中断状态改变");
				}
			}
		};

		executeThread.start();
	}

	public void shutdown(long mills) {
		long currentTime = System.currentTimeMillis();
//判断守护线程是否被执行完毕
		while (!finished) {
//未执行完毕
			if ((System.currentTimeMillis() - currentTime) >= mills) {
//超时
				System.out.println("任务超时,需要结束他!");
//此时想停止守护线程的任务,给被守护线程抛出InterruptedException,守护线程与被守护线程也都可以
//结束掉
				executeThread.interrupt();
				break;
			}
//未超时
			try {
				executeThread.sleep(1);
			} catch (InterruptedException e) {
				System.out.println("执行线程被打断!");
				break;
			}
		}
//执行完毕直接走完被守护线程,守护线程也跟着结束
		finished = false;
	}
}

public class StopThread {
	public static void main(String[] args) throws InterruptedException {
	
		ThreadDemo07 t7  = new ThreadDemo07();
		t7.execute(new Runnable() {
			@Override
			public void run() {
				try {
					long curr = System.currentTimeMillis();
					for(int i = 0;i<50;i++){
						while (true){
							if ((System.currentTimeMillis() - curr) >= 1_000) {
								curr = System.currentTimeMillis();
								System.out.println("我在运行!");
								break;
							}
						}
					}
					//Thread.sleep(2_000);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
		t7.shutdown(3_000);

	}
}

 

大致的思路是把要执行的代码放在守护线程,用一个线程去控制守护线程的终结和开启,这样当被守护线程停止时,守护线程自然也会被结束掉。在shutdown()时调用interrupt,此时被守护线程出于wait状态,会被捕获到异常从而结束该线程生命周期。此时守护线程也就跟着结束掉了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值