版权声明: https://blog.csdn.net/Dongguabai/article/details/84789255
方式一
设置一个是否结束的标志(开关)。
package com.example.threaddesign;
/**
* @author Dongguabai
* @date 2018/12/4 15:16
*/
public class StopThread1 {
private static volatile boolean stop = true;
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(()->{
while (stop){
System.out.println("do sth-----");
}
});
t1.start();
Thread.sleep(10);
stop();
}
public static void stop(){
System.out.println("结束线程1111111");
stop = false;
}
}
方式二
结合 interrupt API。
package com.example.threaddesign;
/**
* @author Dongguabai
* @date 2018/12/4 15:16
*/
public class StopThread2 {
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(() -> {
while (true) {
if (Thread.currentThread().isInterrupted()) {
break;
}
System.out.println("do sth-----");
}
});
t1.start();
Thread.sleep(10);
t1.interrupt();
}
}
使用 interrupt API 也可以使用异常的方式去中断线程,比如可以让当前线程在循环中去 sleep(1),因为这样在执行 interrupt() 方法之后会抛出异常(具体可参看:https://blog.csdn.net/Dongguabai/article/details/82318002)。
但是可以发现方法一与方法二很局限,如果本身在工作的线程中本身就没有加开关,也没有监控是否中断呢,即本身的逻辑无法更改。在 JDK 中的 stop() 方法已经被建议不再使用。那么就可以采用将工作线程进行封装的方式。
方式三
使用 interrupt API + 守护线程的方式。主要应用了用户线程结束后守护线程自动退出的方式去暴力关闭。
package com.example.threaddesign;
import java.util.ArrayList;
/**
* @author Dongguabai
* @date 2018/12/4 15:33
*/
public class ThreadService {
//执行线程
private Thread executor;
private boolean finished = false;
public void execute(Runnable task) {
executor = new Thread() {
@Override
public void run() {
Thread runner = new Thread(task);
runner.setDaemon(true);
//使用守护线程去执行 task
runner.start();
try {
//如果任务执行完成了
runner.join();
//双重防护,如果在规定的超时时间内已经完成了
finished = true;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
executor.start();
}
public void shutdown(long mills) {
long shutdownTime = System.currentTimeMillis();
while (!finished) { //双重防护,如果在规定的超时时间内已经完成了
if (System.currentTimeMillis() - shutdownTime >= mills){
System.out.println("任务超时,强制结束任务!");
executor.interrupt();
break;
}
/*try {
executor.sleep(1);
} catch (InterruptedException e) {
System.out.println("执行线程被打断。。。");
e.printStackTrace();
break;
}*/
//也可以不使用异常抛出的方式
if (executor.isInterrupted()){
System.out.println("执行线程被打断。。。");
//执行线程已被中断
break;
}
}
finished = false;
}
}
可以简单测试一下:
package com.example.threaddesign;
/**
* @author Dongguabai
* @date 2018/12/2 20:58
*/
public class ThreadTest {
public static void main(String[] args) {
System.out.println("任务开启");
long start = System.currentTimeMillis();
ThreadService ts = new ThreadService();
ts.execute(() -> {
while (true) {
//假设不停的在工作,那就必然超时
}
});
ts.shutdown(1000);
long end = System.currentTimeMillis();
System.out.printf("任务已被终止,共耗时【%s】", end - start);
}
}
运行结果:
任务开启
java.lang.InterruptedException
任务超时,强制结束任务!
at java.lang.Object.wait(Native Method)
at java.lang.Thread.join(Thread.java:1245)
at java.lang.Thread.join(Thread.java:1319)
at com.example.threaddesign.ThreadService$1.run(ThreadService.java:26)
任务已被终止,共耗时【1051】
那假如任务 5s 就能结束,而我要求的是 10s,即任务提早结束。
package com.example.threaddesign;
/**
* @author Dongguabai
* @date 2018/12/2 20:58
*/
public class ThreadTest {
public static void main(String[] args) {
System.out.println("任务开启");
long start = System.currentTimeMillis();
ThreadService ts = new ThreadService();
ts.execute(() -> {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
ts.shutdown(10000);
long end = System.currentTimeMillis();
System.out.printf("任务已被终止,共耗时【%s】", end - start);
}
}
运行结果:
任务开启
任务已被终止,共耗时【5056】