概述
本文讲述了最近对线程学习的了解和停止方法,如有问题,希望指出。
在java中有三种方式可以终止线程。分别为:
退出标志,使线程正常退出,也就是当run方法完成后线程终止。
stop方法强行终止线程(这个方法不推荐使用,因为stop和suspend、resume一样,也可能发生不可预料的结果)。
interrupt方法中断线程。
1. 使用退出标志终止线程
- 当run方法执行完后,线程就会退出。
- 但有时run方法是永远不会结束的。如在服务端程序中使用线程进行监听客户端请求,或是其他的需要循环处理的任务。在这种情况下,一般是将这些任务放在一个循环中,如while循环。如果想让循环永远运行下去,可以使用while(true){……}来处理。但要想使while循环在某一特定条件下退出,最直接的方法就是设一个boolean类型的标志,并通过设置这个标志为true或false来控制while循环是否退出。下面给出了一个利用退出标志终止线程的例子。
package chapter2;
public class ThreadFlag extends Thread
{
public volatile boolean exit = false;
public void run()
{
while (!exit);
}
public static void main(String[] args) throws Exception
{
ThreadFlag thread = new ThreadFlag();
thread.start();
sleep(5000); // 主线程延迟5秒
thread.exit = true; // 终止线程thread
thread.join();
System.out.println("线程退出!");
}
}
2. 使用stop方法终止线程
使用stop方法可以强行终止正在运行或挂起的线程。我们可以使用如下的代码来终止线程:
thread.stop();
虽然使用上面的代码可以终止线程,但使用stop方法是很危险的,就象突然关闭计算机电源,而不是按正常程序关机一样,可能会产生不可预料的结果,因此,并不推荐使用stop方法来终止线程。
3. 使用interrupt方法终止线程
使用interrupt方法来终端线程可分为两种情况:
(1)线程处于阻塞状态,如使用了sleep方法。
(2)使用while(!Thread.interrupted()){……}来判断线程是否被中断。
public class ThreadTest {
Thread myRunA;
Thread myRunB;
public class MyRunA implements Runnable{
@Override
public void run() {
//thread stop method 1.
while (true) {
System.out.println("1::" + Thread.currentThread().isInterrupted());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println("MyRunA break....");
break;
}
}
}
}
public class MyRunB implements Runnable{
@Override
public void run() {
//thread stop method 2.
while (true) {
System.out.println("2::" + Thread.currentThread().isInterrupted());
if(Thread.currentThread().isInterrupted()) {
System.out.println("MyRunB break....");
break;
}
}
}
}
public class MyRunInterrupt implements Runnable{
@Override
public void run() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("myRunA ==" + myRunA.isInterrupted() + "----------" + myRunA.getState());
myRunA.interrupt();
System.out.println("myRunA ==" + myRunA.isInterrupted() + "----------" + myRunA.getState());
System.out.println("myRunB ==" + myRunB.isInterrupted() + "----------" + myRunB.getState());
myRunB.interrupt();
System.out.println("myRunB ==" + myRunB.isInterrupted() + "----------" + myRunB.getState());
}
}
public void start() {
myRunA = new Thread(new MyRunA());
myRunA.start();
myRunB = new Thread(new MyRunB());
myRunB.start();
new Thread(new MyRunInterrupt()).start();
}
public static void main(String[] args) {
new ThreadTest().start();
}
}
执行结果如下:
因为线程的执行顺序是不固定的,可能每个人的结果会不一致,但效果是一样的。
科普线程的基础知识
1.thread.interrupt()方法
方法介绍说了一大堆,无非就是描述了3件事。
- 当前方法是中断线程。
- 如果这个线程被阻塞时(比如sleep、wait、join等),会清除中断状态,接收InterruptedException
- 中断非活动的线程,不一定会产生效果
因为stop方法弃用,interrupt方法将会是线程关闭的主流方法。
2.Thread.interrupted()方法
如图所示,测试当前线程是否被中断。
- true:当前线程被中断。
- false:另外的情况。
3.Thread.sleep()方法
调用sleep方法会捕获异常,为什么呢?因为当多线程同时运行时,有两种情况
- 当前线程A运行sleep,线程B调用了A.intertrrupt方法改变线程标志为false,此时sleep会出异常,接收InterruptedException的同时会清除中断状态。
- 当前线程已经被中断,在调用sleep也会接收InterruptedException,清除中断状态。
4.不得不说的InterruptedException
上面讲了很多的InterruptedException异常情况,我们看下官方给出的介绍。
- 在线程等待、睡眠或者其他占用时抛出,线程在活动之前或期间被中断。
- 一个方法可能希望当前线程已被中断,如果是,请立即抛出这个异常。
- 下面的代码可以从来实现这个效果:
if (Thread.interrupted())
throw new InterruptedException();
结论:
1、官方推荐使用这个异常来中断线程,可以在异常里面做结束性的操作。(当然只是限于循环中,因为逻辑简单的情况直接跑完逻辑线程就结束了,不需要中断)
2、Thread.interrupted()与sleep()方法不能同时出现在一起,因为sleep的异常会清除线程状态,与前者验证冲突。