要终止一个线程,并不是简单的调用stop()方法,stop()就像linux中的kill一个线程一样是非常暴力的,虽然在Java的API中仍然可以调用stop()方法,但是和suspend,resume方法一样,是过期了的,不建议使用的,因为stop()在结束一个线程时并不会保证线程的资源正常释放,会导致程序可能会出现一些不确定的状态。
@Deprecated public final void stop() { SecurityManager security = System.getSecurityManager(); if (security != null) { checkAccess(); if (this != Thread.currentThread()) { security.checkPermission(SecurityConstants.STOP_THREAD_PERMISSION); } } // A zero status value corresponds to "NEW", it can't change to // not-NEW because we hold the lock. if (threadStatus != 0) { resume(); // Wake up thread if it was suspended; no-op otherwise } // The VM can handle all thread states stop0(new ThreadDeath()); } @Deprecated public final synchronized void stop(Throwable obj) { throw new UnsupportedOperationException(); }一.interrupt方法 interrupt方法的源码如下:
public void interrupt() { if (this != Thread.currentThread()) checkAccess(); synchronized (blockerLock) { Interruptible b = blocker; if (b != null) { interrupt0(); // Just to set the interrupt flag b.interrupt(this); return; } } interrupt0(); } public static boolean interrupted() { return currentThread().isInterrupted(true); }可以看出,interrupt方法和start方法一样,都是native方法,这要追溯到JVM层面,由于都是C++写的,这里不做深究。 当其他线程调用当前线程的interrupt方法时,即设置了一个标识,表示当前线程可以中断了,至于什么时候中断,取决于当前线程。当前线程通过调用isInterrupted()方法来判断自身是否被中断,如果返回true,则说明当前线程已经中断,这种通过标识位或中断操作的方式能够使线程在终止时有机会清理资源,而这种方式也更加安全。 线程中还提供了静态方法Thread.interrupted()对设置中断标识的线程进行恢复操作,源码是这样描述的:
除了调用interrupted()方法对线程进行恢复操作外,还可以通过抛出interruptedException()异常的方法进行恢复。在抛出interruptedException()异常之前,JVM会先把线程的中断标识位清除,然后才会抛出异常,这时如果调用isInterrupted(),将会返回false。 其实,在interrupt方法的内部,是通过unpark唤醒当前线程,并设置一个标识符为true,并没有真正的中断线程的操作,所以,通过线程的复位操作也可以进行线程之间的通信。 二.volatile关键字 定义一个用volatile修饰的成员变量来控制线程的停止,这点是利用了volatile修饰的成员变量可以在多线程之间达到共享,也就是可见性来实现的,示例代码如下:
public class VolatileDemo { private static volatile boolean flag = false; public static void main(String[] args) throws InterruptedException { new Thread(()->{ int i = 1; while (!flag) { System.out.println(i++); } }).start(); System.out.println("Thread ====== start"); Thread.sleep(1000); flag = true; System.out.println("Thread ====== end"); } }运行结果:
Thread ====== start 1 2 3 。。省略。。 85339 85340 Thread ====== end三.程序运行结束 当一个程序运行结束后,当前线程自然也就终止了。
