线程终止:
在Thread类中JDK给我们提供了一个终止线程的方法stop(); 该方法一经调用就会立即终止该线程,并立即释放对象锁。如果当一个线程执行一半业务而调用了该方法,可能就会产生数据不一致问题。
线程中断:
线程中断就是让目标线程停止执行,但它不会使线程立即终止,而是给线程发送一个通知,告诉线程jvm希望你退出执行,至于目标线程何时退出,则完全由它自己决定(如果立即停止,会造成与stop一样的问题)。
JDK中线程中断的3个相关方法:
//线程中断
public void interrupt(){}
//判断线程是否中断
public boolean isInterrupted() {}
//判断线程是否中断,并清除当前中断状态
public static boolean interrupted(){}
- 中断处于阻塞状态(sleep() / join ()/wait())的线程
public static native void sleep(long millis) throws InterruptedException;
看源码可知sleep() 方法 InterruptedException 中断异常,该异常不是运行时异常,所以需要捕获它,当线程在执行sleep()时,如果发生线程中断,这个异常就会产生。该异常一旦抛出就会清除中断状态。
并且,对InterruptedException的捕获务一般放在while(true)循环体的外面,这样,在产生异常时就退出了while(true)循环。否则,InterruptedException在while(true)循环体之内,就需要额外的添加退出处理。
常用方式:
@Override
public void run() {
try {
while (true) {
// 执行任务...
}
} catch (InterruptedException ie) {
// 由于产生InterruptedException异常,退出while(true)循环,线程终止!
}
}
- 中断处于运行状态的线程
通常,我们通过“标记”方式中断处于“运行状态”的线程。包括“中断标记”与“额外添加标记”。
中断标记方式:
@Override
public void run() {
while (!isInterrupted()) {
// 执行任务...
}
}
额外添加标记:
private volatile boolean flag= true;
protected void stopTask() {
flag = false;
}
@Override
public void run() {
while (flag) {
// 执行任务...
}
}
综上,比较通用的终止线程的方式:
@Override
public void run() {
try {
// 1. isInterrupted()保证,只要中断标记为true就终止线程。
while (!isInterrupted()) {
// 执行任务...
}
} catch (InterruptedException ie) {
// 2. InterruptedException异常保证,当InterruptedException异常产生时,线程被终止。
}
}
示例:
public class Demo1 {
static class MyThread extends Thread{
public MyThread(String name){
super(name);
}
@Override
public void run(){
try{
int i = 0;
while(!isInterrupted()){
Thread.sleep(100);
i++;
System.out.println(Thread.currentThread().getName()+" ("+this.getState()+") loop " + i);
}
} catch (InterruptedException e) {
System.out.println(Thread.currentThread().getName() +" ("+this.getState()+") catch InterruptedException.");
}
}
}
public static void main(String[] args) {
try {
MyThread myThread = new MyThread("myThread");
System.out.println(myThread.getName() +" ("+myThread.getState()+") is new.");
myThread.start();
System.out.println(myThread.getName() +" ("+myThread.getState()+") is started.");
//主线程休眠300ms,然后给主线程发出"中断"指令
Thread.sleep(300);
myThread.interrupt();
System.out.println(myThread.getName() +" ("+myThread.getState()+") is interrupted.");
//主线程休眠300ms,然后查看myThread状态
Thread.sleep(300);
System.out.println(myThread.getName() +" ("+myThread.getState()+") is interrupted now.");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
网友评论