anhuidelinger的专栏

如何停止java的线程一直是一个困恼我们开发多线程程序的一个问题。这个问题最终在Java5的java.util.concurrent中得到了回答:使用,让线程在run方法中停止。

简介

在Java的多线程编程中,java.lang.Thread类型包含了一些列的方法,,and,and。通过这些方法,我们可以对线程进行方便的操作,但是这些方法中,只有方法得到了保留。

在Sun公司的一篇文章《Why are Thread.stop, Thread.suspend and Thread.resume Deprecated?》中详细讲解了舍弃这些方法的原因。那么,我们究竟应该如何停止线程呢?

建议使用的方法

在《Why are Thread.stop, Thread.suspend and Thread.resume Deprecated?》中,建议使用如下的方法来停止线程:

privatevolatileThread blinker;publicvoidstop() { blinker =null; }publicvoidrun() { Thread thisThread = Thread.currentThread();while(blinker == thisThread) {try{ thisThread.sleep(interval); }catch(InterruptedException e){ } repaint(); } }

关于使用volatile关键字的原因,请查看。

当线程处于非运行(Run)状态

当线程处于下面的状况时,属于非运行状态:

当sleep方法被调用。

当wait方法被调用。

当被I/O阻塞,可能是文件或者网络等等。

当线程处于上述的状态时,使用前面介绍的方法就不可用了。这个时候,,我们可以使用来打破阻塞的情况,如:

public void stop() {Thread tmpBlinker = blinker;blinker = null;if (tmpBlinker != null) {tmpBlinker.interrupt();}}

当被调用的时候,InterruptedException将被抛出,所以你可以再run方法中捕获这个异常,让线程安全退出:

try { …. wait();} catch (InterruptedException iex) { throw new RuntimeException("Interrupted",iex);}

阻塞的I/O

当线程被I/O阻塞的时候,调用的情况是依赖与实际运行的平台的。在Solaris和Linux平台上将会抛出InterruptedIOException的异常,但是Windows上面不会有这种异常。所以,我们处理这种问题不能依靠于平台的实现。如:

package com.cnblogs.gpcusterimport java.net.*;import java.io.*;InterruptibleReader extends Thread {private Object lock = new Object( );private InputStream is;private boolean done;private int buflen;protected void processData(byte[] b, int n) { }class ReaderClass extends Thread {public void run( ) {byte[] b = new byte[buflen];while (!done) {try {int n = is.read(b, 0, buflen);processData(b, n);} catch (IOException ioe) {done = true;}}synchronized(lock) {lock.notify( );}}}public InterruptibleReader(InputStream is) {this(is, 512);}public InterruptibleReader(InputStream is, int len) {this.is = is;buflen = len;}public void run( ) {ReaderClass rc = new ReaderClass( );synchronized(lock) {rc.start( );while (!done) {try {lock.wait( );} catch (InterruptedException ie) {done = true;rc.interrupt( );try {is.close( );} catch (IOException ioe) {}}}}}}

另外,我们也可以使用InterruptibleChannel接口。 实现了InterruptibleChannel接口的类可以在阻塞的时候抛出ClosedByInterruptException。如:

package com.cnblogs.gpcusterimport java.io.BufferedReader;import java.io.FileDescriptor;import java.io.FileInputStream;import java.io.InputStream;import java.io.InputStreamReader;import java.nio.channels.Channels;public class InterruptInput {static BufferedReader in = new BufferedReader(new InputStreamReader(Channels.newInputStream((new FileInputStream(FileDescriptor.in)).getChannel())));main(String args[]) {try {System.out.println("Enter lines of input (user ctrl+Z Enter to terminate):");System.out.println("(Input thread will be interrupted in 10 sec.)");// interrupt input in 10 sec(new TimeOut()).start();String line = null;while ((line = in.readLine()) != null) {System.out.println("Read line:’"+line+"’");}} catch (Exception ex) {System.out.println(ex.toString()); // printStackTrace();}}TimeOut extends Thread {int sleepTime = 10000;Thread threadToInterrupt = null;public TimeOut() {// interrupt thread that creates this TimeOut.threadToInterrupt = Thread.currentThread();setDaemon(true);}public void run() {try {sleep(10000); // wait 10 sec} catch(InterruptedException ex) {/*ignore*/}threadToInterrupt.interrupt();}}}

这里还需要注意一点,当线程处于写文件的状态时,调用不会中断线程。

参考资料

How to Stop a Thread or a Task

Why are Thread.stop, Thread.suspend and Thread.resume Deprecated?

但一定要背上几本书,在花海里,草丛旁悠然品味,

anhuidelinger的专栏

相关文章:

你感兴趣的文章:

标签云: