- 正常结束
- 全局变量中断
- interrupt
- stop (线程抛异常,释放所有锁)
interrupt (内容摘自网上)
一、中断一个线程只是为了引起该线程的注意,被中断线程可以决定如何应对中断。
二、对于处于sleep,join等操作的线程,如果被调用interrupt()后,会抛出InterruptedException,然后线程的中断标志位会由true重置为false,因为线程为了处理异常已经重新处于就绪状态。
三、不可中断的操作,包括进入synchronized段以及Lock.lock(),inputSteam.read()等,调用interrupt()对于这几个问题无效,因为它们都不抛出中断异常。如果拿不到资源,它们会无限期阻塞下去。
对于Lock.lock(),可以改用Lock.lockInterruptibly(),可被中断的加锁操作,它可以抛出中断异常。等同于等待时间无限长的Lock.tryLock(long
time, TimeUnit unit)。
对于inputStream等资源,有些(实现了interruptibleChannel接口)可以通过close()方法将资源关闭,对应的阻塞也会被放开。
首先,看看Thread类里的几个方法:
public static boolean interrupted | 测试当前线程是否已经中断。线程的中断状态 由该方法清除。换句话说,如果连续两次调用该方法,则第二次调用将返回 false。 |
---|---|
public boolean isInterrupted() | 测试线程是否已经中断。线程的中断状态 不受该方法的影响。 |
public void interrupt() | 中断线程。上面列出了与中断有关的几个方法及其行为,可以看到interrupt是中断线程。如果不了解Java的中断机制,这样的一种解释极容易造成误解,认为调用了线程的interrupt方法就一定会中断线程。 |
其实,Java的中断是一种协作机制。也就是说调用线程对象的interrupt方法并不一定就中断了正在运行的线程,它只是要求线程自己在合适的时机中断自己。每个线程都有一个boolean的中断状态(这个状态不在Thread的属性上),interrupt方法仅仅只是将该状态置为true。
比如对正常运行的线程调用interrupt()并不能终止他,只是改变了interrupt标示符。
一般说来,如果一个方法声明抛出InterruptedException,表示该方法是可中断的,比如wait,sleep,join,也就是说可中断方法会对interrupt调用做出响应(例如sleep响应interrupt的操作包括清除中断状态,抛出InterruptedException),异常都是由可中断方法自己抛出来的,并不是直接由interrupt方法直接引起的。
Object.wait, Thread.sleep方法,会不断的轮询监听 interrupted
标志位,发现其设置为true后,会停止阻塞并抛出 InterruptedException异常。
测试代码
package com;
import com.entity.Data;
import java.util.*;
import java.util.concurrent.*;
/**
* interrupt()是给线程设置中断标志;
* interrupted()是检测中断并清除中断状态;
* isInterrupted()只检测中断。
*
* interrupted()作用于当前线程,interrupt()和isInterrupted()作用于此线程,
*/
public class ThreadTest {
// 全局变量方式结束线程
static volatile boolean exitFlag = false;
public static void main(String[] args) {
// test1();
// test2();
test3();
}
// 全局变量方式结束线程
public static void test1(){
Runnable runnable1 = new Runnable() {
@Override
public void run() {
while (!exitFlag){
System.out.println(new Date().getTime());
try {
Thread.sleep(5*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
Thread thread = new Thread(runnable1);
thread.start();
Scanner sc = new Scanner(System.in);
while (true){
System.out.println("输入t 结束线程");
String df = sc.next();
if ("t".equals(df)){
exitFlag = true;
}
}
}
// interrupt 方式1结束线程 当线程处于阻塞时 调用 interrupt(中断) 方法抛异常 跳出结束线程
public static void test2(){
Runnable runnable1 = new Runnable() {
@Override
public void run() {
while (true){
System.out.println(new Date().getTime());
try {
Thread.sleep(5*1000);
} catch (InterruptedException e) {
e.printStackTrace();
break ;
}
}
System.out.println("线程执行完成");
}
};
Thread thread = new Thread(runnable1);
thread.start();
Scanner sc = new Scanner(System.in);
while (true){
System.out.println("输入t 结束线程");
String df = sc.next();
if ("t".equals(df)){
thread.interrupt();
}
}
}
// interrupt 方式2结束线程 (常用)
public static void test3(){
Thread thread = new MyThread();
thread.start();
Scanner sc = new Scanner(System.in);
while (true){
System.out.println("输入t 结束线程");
String df = sc.next();
if ("t".equals(df)){
thread.interrupt();
}else {
thread.interrupted();
}
}
}
static class MyThread extends Thread{
@Override
public void run() {
while (true){
long time = System.currentTimeMillis();
while ((System.currentTimeMillis() - time < 1000) ) {
}
if (!Thread.currentThread().isInterrupted()){
System.out.println(time);
}else {
System.out.println("恢复中断");
}
// interrupted()作用于当前线程 恢复中断
// System.out.println("...::" + Thread.currentThread().interrupted());
}
}
}
}