概述

本文讲述了最近对线程学习的了解和停止方法,如有问题,希望指出。

在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();
	}
}

执行结果如下:

Java怎么停止指定的异步多线程 java停止线程的方法_JAVA

因为线程的执行顺序是不固定的,可能每个人的结果会不一致,但效果是一样的。

 

科普线程的基础知识

1.thread.interrupt()方法

Java怎么停止指定的异步多线程 java停止线程的方法_System_02

方法介绍说了一大堆,无非就是描述了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

Java怎么停止指定的异步多线程 java停止线程的方法_Java怎么停止指定的异步多线程_03

上面讲了很多的InterruptedException异常情况,我们看下官方给出的介绍。

  • 在线程等待、睡眠或者其他占用时抛出,线程在活动之前或期间被中断。
  • 一个方法可能希望当前线程已被中断,如果是,请立即抛出这个异常。
  • 下面的代码可以从来实现这个效果:
if (Thread.interrupted())
    throw new InterruptedException();

结论:

1、官方推荐使用这个异常来中断线程,可以在异常里面做结束性的操作。(当然只是限于循环中,因为逻辑简单的情况直接跑完逻辑线程就结束了,不需要中断)

2、Thread.interrupted()与sleep()方法不能同时出现在一起,因为sleep的异常会清除线程状态,与前者验证冲突。