开启线程都知道了,怎么中断一个线程呢?
这里的中断也叫终止、停止,意思都是停止一个正在运行的线程。
在线程的执行逻辑中添加标志位判断,
需要中断线程时,修改该标志位,让线程执行逻辑结束。
public class StopThreadTest {
public static void main(String[] args) throws InterruptedException {
FThread fThread = new FThread();
fThread.start();
Thread.sleep(3000);
fThread.setFlag(true);
}
}
class FThread extends Thread{
private boolean flag_stop = false;
@Override
public void run() {
super.run();
for (int t = 0; t < 10000; t++){
if (flag_stop) {
break;
}
System.out.println("FThread[" + Thread.currentThread().getName() + "] working , t = " + t);
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
}
// real function
}
System.out.println("FThread[" + Thread.currentThread().getName() + "] finish");
}
public void setFlag(boolean flag){ this.flag_stop = flag; }
}
在线程的执行逻辑中添加对中断的判断,判断方法是 isInterrupted()
,
需要中断某个线程时,调用 interrupt
方法。
interrupt
方法的 API 说明:
Interrupts this thread.
Unless the current thread is interrupting itself, which is always permitted, the checkAccess method of this thread is invoked, which may cause a SecurityException to be thrown.
If this thread is blocked in an invocation of the wait(), wait(long), or wait(long, int) methods of the Object class, or of the join(), join(long), join(long, int), sleep(long), or sleep(long, int), methods of this class, then its interrupt status will be cleared and it will receive an InterruptedException.
If this thread is blocked in an I/O operation upon an InterruptibleChannel then the channel will be closed, the thread’s interrupt status will be set, and the thread will receive a java.nio.channels.ClosedByInterruptException.
If this thread is blocked in a java.nio.channels.Selector then the thread’s interrupt status will be set and it will return immediately from the selection operation, possibly with a non-zero value, just as if the selector’s wakeup method were invoked.
If none of the previous conditions hold then this thread’s interrupt status will be set.
Interrupting a thread that is not alive need not have any effect.
Throws:
SecurityException – if the current thread cannot modify this thread
概括:
直接用试试,
public class StopThreadTest {
public static void main(String[] args) throws InterruptedException {
CalculateThread thread1 = new CalculateThread("thread1");
thread1.start();
thread1.interrupt();
}
}
class CalculateThread extends Thread{
private String name;
public CalculateThread(String name) {
super(name);
this.name = name;
}
@Override
public void run() {
super.run();
for (int i = 0; i < 10000 ; i++){
if (this.isInterrupted()) {
System.out.println("Thread[" + name + "] isInterrupted, exit");
break;
}
System.out.println("Thread[" + name + "] is running, i = " + i);
}
System.out.println("Thread[" + name + "] finish");
}
}
运行结果,
Thread[thread1] isInterrupted, exit
Thread[thread1] finish
一开始就中断,太快了,没看清,加个延时试试。
假设线程中有用 sleep() 方法,看看有什么不一样
public class StopThreadTest {
public static void main(String[] args) throws InterruptedException {
CalculateThread thread1 = new CalculateThread("thread1");
thread1.start();
Thread.sleep(2000);
thread1.interrupt();
}
}
class CalculateThread extends Thread{
private String name;
public CalculateThread(String name) {
super(name);
this.name = name;
}
@Override
public void run() {
super.run();
for (int i = 0; i < 10000 ; i++){
if (this.isInterrupted()) {
System.out.println("Thread[" + name + "] isInterrupted, exit");
break;
}
System.out.println("Thread[" + name + "] is running, i = " + i);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
System.out.println("InterruptedException");
e.printStackTrace();
}
}
System.out.println("Thread[" + name + "] finish");
}
}
运行结果,
Thread[thread1] is running, i = 0
InterruptedException
Thread[thread1] is running, i = 1
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at com.lah.thread.CalculateThread.run(StopThreadTest.java:68)
Thread[thread1] is running, i = 2
Thread[thread1] is running, i = 3
Thread[thread1] is running, i = 4
Thread[thread1] is running, i = 5
Thread[thread1] is running, i = 6
//后面的继续执行,没成功,省略了
在 sleep() 时被中断,发生了 InterruptedException 异常,和 API 中说明的一样。
解决办法:做好异常处理逻辑
。
本例,直接在异常时 break 退出即可,
class CalculateThread extends Thread{
private String name;
public CalculateThread(String name) {
super(name);
this.name = name;
}
@Override
public void run() {
super.run();
for (int i = 0; i < 10000 ; i++){
if (this.isInterrupted()) {
System.out.println("Thread[" + name + "] isInterrupted, exit");
break;
}
System.out.println("Thread[" + name + "] is running, i = " + i);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
System.out.println("InterruptedException");
e.printStackTrace();
break; // 这里
}
}
System.out.println("Thread[" + name + "] finish");
}
}
再次运行就可以中断线程了,
Thread[thread1] is running, i = 0
Thread[thread1] is running, i = 1
InterruptedException
Thread[thread1] finish
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at com.lah.thread.CalculateThread.run(StopThreadTest.java:68)
线程的 stop() 方法是弃用的 API ,不推荐使用。