Java中终止线程有哪几种方式?

在讨论线程终止的方式前,我们先讨论一个问题,线程和进程有什么区别?
简而言之,进程是程序运行和资源分配的基本单位,一个程序至少有一个进程,一个进程至少有一个线程(一个进程可以包含多个线程)。进程在执行过程中拥有独立的内存单元,而多个线程共享内存资源,减少切换次数,从而效率更高。线程是进程的一个实体,是cpu调度和分派的基本单位,是比程序更小的能独立运行的基本单位。同一进程中的多个线程之间可以并发执行。

线程有哪些状态?
线程通常都有五种状态,新建(New)、就绪(Runnable)、运行(Running)、阻塞(Blocked)和死亡(Dead)。
1、新建状态:当程序使用new关键字创建了一个线程对象后,该线程就处于新建状态,此时仅由JVM为其分配内存,并初始化其成员变量的值,在未调用该对象的start方法之前,线程都处于新建状态。

2、就绪状态:当线程对象调用了start()方法之后,该线程就进入了就绪状态。Java虚拟机会为其创建方法调用栈和程序计数器,等待调度运行。但是此时线程调度程序还没有把该线程设置为当前线程,此时处于就绪状态。在线程运行之后,从等待或者睡眠中回来之后,也会处于就绪状态。

3、运行状态:如果处于就绪状态的线程获得了 CPU,开始执行 run()方法的线程执行体,则该线程处于运行状态;也就是线程调度程序将处于就绪状态的线程设置为当前线程,开始运行run函数当中的代码。

4、阻塞状态:线程正在运行的时候,被暂停,通常可以理解为指线程因为某种原因放弃了cpu使用权,sleep,suspend,wait等方法都可以导致线程阻塞。阻塞的情况分3种,分别是等待阻塞、同步阻塞和其他阻塞。

5、死亡状态:如果一个线程的run方法执行结束或者调用stop方法后,该线程就会死亡。对于已经死亡的线程,无法再使用start方法令其进入就绪。

Java中终止线程有哪几种方式?

1、正常运行结束:如果面试问到这个问题,一般人都会想不到有一种方式可以正常终止线程,那就是正常运行结束。

2、使用退出标志退出线程:使用退出标识,使得线程正常退出,即当run方法完成后进程终止。

public class ThreadTest extends Thread {

	public static boolean exit = true;

	// 重写run方法,run方法的方法体就是现场执行体
	public void run() {
		while (!exit) {
			System.out.println("线程终止!");
			try {
				Thread.sleep(5000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println("结束!");
			break;
		}
	}

	public static void main(String[] args) {
		exit = false;
		new ThreadTest().start();
	}

}

3、使用interrupt方法中断线程

需要注意的是:interrupt()方法不像stop方法强行终止一个线程,它只是把要被停止的线程设置成中断状态,而此时要被中断的线程是可以继续执行的。

public class ThreadTest extends Thread {
	// 重写run方法,run方法的方法体就是现场执行体
	@Override
	public void run() {
		super.run();
		for (int i = 0; i < 4; i++) {
			if (this.isInterrupted()) {
				System.out.println("线程已经结束!");
				break;
			}
			System.out.println("i=" + (i + 1));
		}
		System.out.println("我要证明线程未真正结束!");

	}

	public static void main(String[] args) {
		try {
			ThreadTest thTest = new ThreadTest();
			thTest.start();
			Thread.sleep(20);
			thTest.interrupt();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

}


程序执行结果:
i=1
i=2
i=3
i=4
我要证明线程未真正结束!

所以,使用interrupt()方法来中断线程需要考虑两种情况:

1)线程处于阻塞状态:如使用了sleep,同步锁的wait,socket中的receiver,accept等方法时,会使线程处于阻塞状态。当调用线程的interrupt()方法时,会抛出InterruptException异常。阻塞中的那个方法抛出这个异常,通过代码捕获该异常,然后break跳出循环状态,从而让我们有机会结束这个线程的执行。这种方法也叫做抛异常法。

public class ThreadTest extends Thread {
	// 重写run方法,run方法的方法体就是现场执行体
	@Override
	public void run() {
		super.run();
		try {
			for (int i = 0; i < 1000; i++) {
				if (this.isInterrupted()) {
					System.out.println("线程已经结束!");
					// 改动break为抛出异常(抛异常法)
					throw new InterruptedException();
				}
				System.out.println("i=" + (i + 1));
			}

			System.out.println("我想证明抛异常的时候线程已经结束了,可惜没办法输出!");
		} catch (InterruptedException e) {
			System.out.println("捕获InterruptedException异常");
			e.printStackTrace();
		}
		System.out.println("我要证明我是否还活着");

	}

	public static void main(String[] args) {
		try {
			ThreadTest thTest = new ThreadTest();
			thTest.start();
			Thread.sleep(20);
			thTest.interrupt();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

}

循环中设置的数值越大,效果越明显。通常很多人认为只要调用interrupt方法线程就会结束,实际上是错的,一定要先捕获InterruptedException 异常之后通过break来跳出循环,才能正常结束run方法。

2)线程未处于阻塞状态:使用isInterrupted()判断线程的中断标志来退出循环。当使用interrupt()方法时,中断标志就会置true,和使用自定义的标志来控制循环是一样的道理。

isInterrupted()和interrupted()方法有什么区别?

isInterrupted()判断的是调用它的对象所启动的线程是否处于中断状态,而不是判断当前线程。

interrupted()方法是静态方法,它判断的是当前线程是否中断

public class ThreadTest extends Thread {
	// 重写run方法,run方法的方法体就是现场执行体
	@Override
	public void run() {
		super.run();
		try {
			for (int i = 0; i < 1000; i++) {
				if (this.isInterrupted()) {
					System.out.println("线程已经结束!");
					// 改动break为抛出异常(抛异常法)
					throw new InterruptedException();
				}
				System.out.println("i=" + (i + 1));
			}

			System.out.println("我想证明抛异常的时候线程已经结束了,可惜没办法输出!");
		} catch (InterruptedException e) {
			System.out.println("捕获InterruptedException异常");
			e.printStackTrace();
		}
		System.out.println("我要证明我是否还活着");

	}

	public static void main(String[] args) {
		try {
			ThreadTest thTest = new ThreadTest();
			thTest.start();
			Thread.sleep(20);
			thTest.interrupt();
//			System.out.println("1interrupted thread is stop=" + thTest.interrupted()); //false
//			System.out.println("2interrupted thread is stop=" + thTest.interrupted()); //false
			System.out.println("1isInterrupted thread is stop=" + thTest.isInterrupted()); //true
			System.out.println("2isInterrupted thread is stop=" + thTest.isInterrupted()); //true
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	
}
发布了224 篇原创文章 · 获赞 34 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/weixin_39309402/article/details/104933545