`

[#0x004B] Java多线程:终止线程的方法

    博客分类:
  • Java
阅读更多

  虽说Thread类提供了stop()和suspend()方法,但这两种方法过于粗暴,如果线程占用了一些资源(如打开了一个文件,建立了一个数据库连接什么的),直接stop()或是suspend()是会产生问题的。

 

  要终止Thread,最好的方法就是让run()方法正常运行完毕,不过有的run()方法里面直接是一个while (true),这时就要使用一些特殊的手段。

 

1. 使用中断

  基本思想就是在run()方法中的while (true)里检查线程是否中断,如果中断就退出(当然,退出之前可以做一些关闭资源的操作);这么一来在主线程中就可以调用Thread.interrupt()来中断线程,进而使线程退出。

public class Runner3 implements Runnable {   
	@Override  
	public void run() {   
		while(true) {   
			System.out.println(new Date());   
               
			long time = System.currentTimeMillis();   
			while (System.currentTimeMillis() - time < 1000) {   
				// 不使用Thread.sleep(1000)   
				// 使用while来消耗一秒钟时间   
			}   
               
			if (Thread.currentThread().isInterrupted()) { // 时刻检查该线程是否中断   
			// 或者使用 if (Thread.interrupted()) {   
				return; // 如果线程中断就退出   
			}   
		}   
	}   
}  

 

public class MultiThreadTest3 {   
	public static void main(String[] args) {   
		Runner3 r = new Runner3();   
  
		Thread t = new Thread(r);   
		t.start();   
           
		try {   
			Thread.sleep(10000);   
		} catch (InterruptedException e) {   
			// do nothing   
		}   
           
		t.interrupt(); // 中断Thread t,使run()方法退出,线程结束   
	}   
}  

 

  如果在run()方法中的while (true)里有可能导致InterruptedException的操作,那么退出run()方法的代码可以放在catch语句里。

public class Runner2 implements Runnable {
	@Override
	public void run() {
		while(true) {
			System.out.println(new Date());
			
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				return; // 发生中断异常时,线程直接退出
			}
		}
	}
} 

 

public class MultiThreadTest2 {   
	public static void main(String[] args) {   
		Runner2 r = new Runner2();   
  
		Thread t = new Thread(r);   
		t.start();   
           
		try {   
			Thread.sleep(10000);   
		} catch (InterruptedException e) {   
			// do nothing   
		}   
           
		t.interrupt(); // 中断Thread t,使t.sleep()时产生中断异常,进而终止线程   
	}   
}  

 

2. 使用标志位

   使用标志位boolean flag,将run()方法中的while (true)改为while (flag)(轮询标志位),主线程中就就可以通过修改flag来退出线程。

public class Runner4 implements Runnable {
	private boolean flag = true;
	
	public void setFlag(boolean flag) {
		this.flag = flag;
	}

	@Override
	public void run() {
		while(flag) {
			System.out.println(new Date());
			
			long time = System.currentTimeMillis();
			while (System.currentTimeMillis() - time < 1000) {
				// 不使用Thread.sleep(1000)
				// 使用while来消耗一秒钟时间
			}
		}
	}
}

 

public class MultiThreadTest4 {
	public static void main(String[] args) {
		Runner4 r = new Runner4();

		Thread t = new Thread(r);
		t.start();
		
		try {
			Thread.sleep(10000);
		} catch (InterruptedException e) {
			// do nothing
		}
		
		r.setFlag(false); // 设置标志位,使run()方法退出,线程结束
	}
}

 

  这个方法有一个缺点:如果while (flag) {...}方法阻塞了,则flag的设置会失效。

 

 

 

 

3. 最好的方法是使用线程池

  当线程不用了,就让它sleep并放进队列中,这样可以最大限度地利用资源。不过这暂时不在本文的讨论范围内。

 

 

2010-10-04 补充:
  注意这里说的退出是这样的一种情况:主线程(比如说 main 方法)创建了一个 Thread t,然后想在主线程中使t退出。
  文章一开始说的 stop()、suspend() 方法的问题是:主线程一句 t.stop() 或是 t.suspend() 就了事了,t 在 run() 方法中没有机会去关闭资源,不像中断或是轮询标志位的方法中,t 在 run() 方法里还握有一点主动权

 

 

2011-11-03 补充:

  方法2可以使用的一个优化步骤是将标志位设置为 volatile

分享到:
评论
1 楼 a455642158 2012-06-16  
基本思想就是在run()方法中的while (true)里检查线程是否中断,如果中断就退出(当然,退出之前可以做一些关闭资源的操作);这么一来在主线程中就可以调用Thread.interrupt()来中断线程,进而使线程退出。
我现在不检查,就想直接退出,有什么方法可以吗……?
还有括号里这句:当然,退出之前可以做一些关闭资源的操作→不怎么会啊。

相关推荐

Global site tag (gtag.js) - Google Analytics