停止线程的3种方法

在介绍停止线程的方法前,先介绍几个方法作为预备知识:

1、interrupt()
这个方法的作用是使得调用该方法的线程的interrupted状态为true。注意,这个方法并不是直接停止线程,它只是修改线程的interrupted状态位,相当于给该线程打了个“需要停止”的标记。我们可以通过实验来验证这一现象:

public class Test2 {

	public void print() {
		for (int i = 0; i < 500000; i++) {
			System.out.println("i=" + i);
			if (Thread.currentThread().isInterrupted()) {
				System.out.println("被interrupt了:" + Thread.currentThread().isInterrupted());
			}
		}
	}
	
	public static void main(String[] args) throws InterruptedException {
		Test2 test2 = new Test2();
		Thread t1 = new Thread(() -> {
			test2.print();
		}, "t1");
		t1.start();
		Thread.sleep(500);
		t1.interrupt();
	}
}

执行结果:
停止线程的3种方法_第1张图片
可以看到,虽然线程t1的interrupted状态早已为true,但是循环还是会继续下去,线程t1并未停止

2、interrupted()
这个方法的作用是返回当前线程的interrupted状态,“当前线程”指的是当前正在运行的线程。这个方法是static方法,推荐用Thread.interrupted()方式来调用。注意,调用该方法的线程,它的interrupted状态会被重置为false,即在某个线程调用interrupt()后,第一次调用Thread.interrupted()返回为True,然后什么都不做立即第二次调用Thread.interrupted(),返回的将会是False。我们可以从源码中验证这一点:
停止线程的3种方法_第2张图片

3、isInterrupted()
这个方法的作用是返回调用该方法的线程的interrupted状态。要注意和interrupted()方法进行区分。调用该方法的线程,不一定是当前正在运行的线程。比如有两个线程t1和t2,此时t2正在运行,然后t2的逻辑中有一步是t1.isInterrupted(),这一步返回的是线程t1的interrupted状态,而不是正在运行的t2的interrupted状态。而且这个方法并不会重置调用该方法的线程的interrupted状态,我们可以从源码中验证这一点:
停止线程的3种方法_第3张图片
接下来介绍停止线程的方法
1、抛出异常法:
具体方法就是在线程run()方法内部用try/catch将整个run方法内部代码括起来,加上该线程的interrupted状态判断,若为true,则抛出异常,此时线程会停止。

public class Test2 {

	public static void main(String[] args) throws Exception {
		Thread thread = new Thread(new MyThread(), "t1");
		thread.start();
		Thread.sleep(500);
		thread.interrupt();
	}
}

class MyThread implements Runnable {

	@Override
	public void run() {
		try {
			for (int i = 0; i < 500000; i++) {
				System.out.println("i=" + i);
				if (Thread.interrupted()) {
					System.out.println("线程要停止了...");
					throw new InterruptedException();
				}
			}
		} catch (InterruptedException e) {
			System.out.println("进入catch");
		} finally {
			System.out.println("线程停止时的收尾处理。。。");
		}
	}
}

执行结果:
停止线程的3种方法_第4张图片
2、return停止法:
在run()方法内部加上该线程的interrupted状态判断,若为true,则可以用return直接退出run()方法。

public class Test2 {

	public static void main(String[] args) throws Exception {
		Thread thread = new Thread(new MyThread(), "t1");
		thread.start();
		Thread.sleep(500);
		thread.interrupt();
	}
}

class MyThread implements Runnable {

	@Override
	public void run() {
		for (int i = 0; i < 500000; i++) {
			System.out.println("i=" + i);
			if (Thread.interrupted()) {
				System.out.println("线程要停止了...");
				System.out.println("收尾工作...");
				return;
			}
		}
	}
}

执行结果:
停止线程的3种方法_第5张图片
3、用stop()方法停止(不推荐,而且该方法已过时):
调用stop()方法的线程会立即停止,无法在线程停止前进行一些收尾工作,比如该线程的一个事务还未执行完,此时该线程被stop了,我们是无法将这个事务回滚的,这样就造成了数据不一致的问题。

public class Test {
	private String user = "u1";
	private String pwd = "p1";
	
	public synchronized String getUser() {
		return user;
	}
	public void setUser(String user) {
		this.user = user;
	}
	public synchronized String getPwd() {
		return pwd;
	}
	public void setPwd(String pwd) {
		this.pwd = pwd;
	}
	
	public synchronized void print(String user, String pwd) throws InterruptedException {
		this.user = user;
		Thread.sleep(1000);
		this.pwd = pwd;
	}
	
	public static void main(String[] args) throws InterruptedException {
		Test test = new Test();
		
		Thread thread = new Thread(() -> {
			try {
				test.print("u2", "p2");
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		});
		thread.start();
		Thread.sleep(500);
		thread.stop();
		System.out.println(test.getUser() + "===" + test.getPwd());
	}
}

执行结果:
在这里插入图片描述

你可能感兴趣的:(java多线程,java,多进程)