1. void java.lang.Thread.interrupt()
线程中断究竟做了什么?这里有关于该问题的详细回答。
调用Thread.interrupt()方法后,目标线程的中断状态被更新了。在目标线程中运行的代码可能会记下中断状态并在之后做好善后处理。一些方法比如Object.wait()将会立即响应此中断状态并立即抛出对应的异常(通常是InterruptedException).
相较而言,线程的中断是一种温和的方式作用于线程的;它给了线程一种干净地退出线程的机会,这是相较于之前的Thread.stop()方法而言的。
2.如何有效地退出线程?
这里有关于该问题的详细Q&A.
在对于给定的线程thread.interrupt()之后,只是对于线程设置了标记,并没有立即改变线程的运行状态。如何优雅地退出当前执行的线程任务呢?
2种方式:
1). 通过当前线程非静态方法thread.isInterrupted()在run()方法里返回,或在循环控制条件中加控制
2). 设置volatile boolean 类型的flag,周期性检验该flag的值
package com.fqyuan.interrupt;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class TestStop {
public static void main(String[] args){
ExecutorService executor = Executors.newCachedThreadPool();
executor.submit(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
}
});
}
}
class MyThread1 extends Thread {
volatile boolean finished = false;
public void stopMe() {
finished = true;
}
public void run() {
while (!finished) {
// Do dirty work.
try {
Thread.sleep(1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
class MyThread2 extends Thread {
public void run() {
while (!Thread.currentThread().isInterrupted()) {
// doFirstPartOfWorK();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
//Restore the interrupt flag.
Thread.currentThread().interrupt();
}
// doSecondPartOfWork();
}
}
}
3. 代码及运行结果
package com.fqy.mix;
public class GeneralInterrupt implements Runnable {
public void run() {
try {
System.out.println("in run() - about to work()");
work();
System.out.println("in run() - back from work()");
} catch (InterruptedException x) {
System.out.println("in run() - interrupted in work()");
return;
}
System.out.println("in run() - doing stuff after nap");
System.out.println("in run() - leaving normally");
}
public void work2() throws InterruptedException {
while (true) {
if (Thread.currentThread().isInterrupted()) {
System.out.println("C isInterrupted()=" + Thread.currentThread().isInterrupted());
Thread.sleep(2000);
System.out.println("D isInterrupted()=" + Thread.currentThread().isInterrupted());
}
}
}
public void work() throws InterruptedException {
while (true) {
// Time consuming operation here.
for (int i = 0; i < 1E7; i++) {
// !Thread.currentThread().isInterrupted()
// int j = i * 2;
if (Thread.currentThread().isInterrupted())
break;
Math.sin(i);
}
/*
* Test whether this thread has been interrupted. The interrupted
* status of the thread is unaffected by the method. This is
* non-static method here.
*/
System.out.println("A isInterrupted()=" + Thread.currentThread().isInterrupted());
/*
* Test whether the current thread has been interrupted. The
* interrupted status of the thread is cleared by the method. That's
* to say, the second call will return false. And this is a static
* method.
*/
if (Thread.interrupted()) {
System.out.println("B isInterrupted()=" + Thread.currentThread().isInterrupted());
throw new InterruptedException();
}
}
}
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
GeneralInterrupt si = new GeneralInterrupt();
Thread t = new Thread(si);
t.start();
try {
Thread.sleep(2000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
System.out.println("in main() - interrupting other thread");
t.interrupt();
System.out.println("in main() - leaving");
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
long endTime = System.currentTimeMillis();
System.out.println("Total time taken is: " + (endTime - startTime));
}
}
运行结果:
in run() - about to work()
in main() - interrupting other thread
in main() - leaving
A isInterrupted()=true
B isInterrupted()=false
in run() - interrupted in work()
Total time taken is: 2005
4.另一个例子
package com.fqy.cave;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class InterruptionDemo1 {
public static void main(String[] args) {
InterruptionUtil.demonstrate();
}
}
class InterruptionUtil {
public static void demonstrate() {
ExecutorService executor = Executors.newCachedThreadPool();
executor.submit(new Runnable() {
@Override
public void run() {
Random random = new Random();
for (int i = 0; i < 1E8; i++) {
/*
* 为什么这里的break是必要的?
* 1)线程的状态并没有被isInterrupted改变,所以如果注释了break就会一直执行
* 2)interrupted是个静态方法,改变了线程状态。
*/
if (Thread.currentThread().isInterrupted()) {
System.out.println(Thread.currentThread().getName() + " is Interrupted!");
break;
}
Math.sin(random.nextDouble());
}
}
});
System.out.println(Thread.currentThread().getName() + " is going to sleep for 1000ms.");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
executor.shutdownNow();
try {
executor.awaitTermination(1, TimeUnit.DAYS);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Finished!");
}
}
结果:
main is going to sleep for 1000ms.
pool-1-thread-1 is Interrupted!
Finished!
5.关于interrupt()/Thread.interrupted()/Thread.isInterrupted()方法。
Thread.interrupt(): 中断当前线程。
Thread.interrupted(): 静态方法,测试当前线程是否被中断,当前线程的中断状态被置0;
Thread.isInterrupted(): 非静态方法,测试当前线程的状态,不改变线程的中断状态。
这里或许有相关代码和笔记。