强制停止一个线程是不安全的,线程什么时候可以停止,只有线程自己知道,我们模拟主线程中启动一个工作线程,主线程睡眠3秒后去停止工作线程。
public class ThreadCloseGraceful {
private static class Worker extends Thread {
private volatile boolean running = true;
public Worker(String name) {
super(name);
}
@Override
public void run() {
String threadName = Thread.currentThread().getName();
while (running) {
System.out.println(threadName + " is running");
try {
Thread.sleep(1_000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(threadName + " exit");
}
public void shutdown() {
this.running = false;
}
}
public static void main(String[] args) {
Worker worker = new Worker("Worker");
worker.start();
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
worker.shutdown();
}
}
使用volatile关键字保证内存可见性,主线程修改了,工作线程可以立刻知道running字段的内容变化。如果工作线程已经阻塞了,这种方法没有办法停止,这种情况可以使用线程的interrupt()方法。
public class ThreadCloseGraceful2 {
private static class Worker extends Thread {
public Worker(String name) {
super(name);
}
@Override
public void run() {
String threadName = Thread.currentThread().getName();
while (true) {
System.out.println(threadName + " is running");
try {
Thread.sleep(10_000);
} catch (InterruptedException e) {
e.printStackTrace();
break;
}
}
System.out.println(threadName + " exit");
}
}
public static void main(String[] args) {
Worker worker = new Worker("Worker");
worker.start();
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
worker.interrupt();
}
}
我们调用interrupt()方法后
apache工具包中的FileAlterationMonitor文件变化监控器就是通过标志位和中断来实现的。
public class ThreadService {
private Thread executeThread;
private boolean finished = false;
public void execute(Runnable task) {
executeThread = new Thread(() -> {
Thread runner = new Thread(task);
runner.setDaemon(true);
runner.start();
try {
runner.join();
finished = true;
} catch (InterruptedException e) {
//ignore
}
});
executeThread.start();
}
public void shutdown(long mills) {
long currentTime = System.currentTimeMillis();
while (!finished) {
if ((System.currentTimeMillis() - currentTime) >= mills) {
System.out.println("任务超时,需要结束他!");
executeThread.interrupt();
break;
}
try {
Thread.sleep(1);
} catch (InterruptedException e) {
System.out.println("执行线程被打断!");
break;
}
}
finished = false;
}
}
客户端调用
public class ThreadCloseForce {
public static void main(String[] args) throws InterruptedException {
ThreadService service = new ThreadService();
long start = System.currentTimeMillis();
service.execute(() -> {
//load a very heavy resource.
/*while (true) {
}*/
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
service.shutdown(3000);
System.out.println("main start");
long end = System.currentTimeMillis();
System.out.println(end - start);
}
}
在工作线程内启动一个新的守护线程,当主线程停止工作线程时,会向工作线程发中断信号,就算工作线程在执行一个费时的操作,也会被停止。
java多线程正确关闭的方法
如何优雅的关闭Java线程池
java 如何优雅的停止一个线程
原文:https://www.cnblogs.com/strongmore/p/14697508.html