一 .概述
在jdk之中之前又一个stop方法可以关闭线程,但是那个方法存在线程安全的问题,现在已经被废除掉了.
之后就没有出现关闭线程的方法了.
但是在我们的使用过程之中,我们需要关闭线程,这个时候,我们就需要用其它的方式来完成线程的关闭操作.
二 . 使用标记位完成
public class StopThread { private static class task implements Runnable { // 标记位 private volatile boolean flag = true; public void run() { while (flag) { System.out.println("running ..."); } } public void shutdown() { this.flag = false; } } public static void main(String[] args) throws Exception { task task = new task(); Thread thread = new Thread(task); thread.start(); // 主线程休眠三秒之后 修改标记位 TimeUnit.SECONDS.sleep(3); task.shutdown(); } }
以上的方式时可以完成任务的,但是需要不断的监听标记位.
三 . 使用interrupt的方式
public class InterruptThread { private static class Task implements Runnable { public void run() { try { for (;;) { TimeUnit.MICROSECONDS.sleep(100); System.out.println("thread is running ... "); } } catch (Exception e) { return ; } } } public static void main(String[] args) throws Exception { Thread thread = new Thread(new Task()); thread.start(); // 主线程休眠3秒之后,主动打断任务线程 TimeUnit.SECONDS.sleep(3); thread.interrupt(); } }
在主线程休眠3秒之后,主动打断子线程,子线程的sleep方法会抛出异常我们捕获异常就能终止线程的运行了.
在这里我们使用的是sleep方法,同时我们也可以用判断的方式.
public class InterruptThread { private static class Task implements Runnable { public void run() { for (;;) { // TimeUnit.MICROSECONDS.sleep(100); if (!Thread.interrupted()) System.out.println("thread is running ... "); else return; } } } public static void main(String[] args) throws Exception { Thread thread = new Thread(new Task()); thread.start(); // 主线程休眠3秒之后,主动打断任务线程 TimeUnit.SECONDS.sleep(3); thread.interrupt(); } }
相对来说,我们用判断的方式还是比较好的.
四 .暴力停止线程
当我们的任务花费的时间比较长的时候,我们的循环判断是根本没有触发的时候,这个时候我们就需要使用暴力的方式强制线程停止.
public class ThreadService { //执行线程,相当于一个主线程... private Thread executeThread; public void startThread(final Runnable task) { // 创建执行线程,这个线程就是一个主线程 executeThread = new Thread() { @Override public void run() { // 开启子线程 Thread childThread = new Thread(task); // 设置子线程为守护进程 childThread.setDaemon(true); // 开启子线程的任务 childThread.start(); // 父线程一直线循环 try { //主线程一直让子线程运行 childThread.join(); } catch (InterruptedException e) { // 当主线程被打断的时候,直接终止自己的运行 // nothing to do System.out.println("收到了终结主线程的信号了,现在我需要停止了"); System.out.println("我带的守护线程也需要终结了.."); return ; // 终结主线程,子线程随之被杀死 } } }; //开启执行线程 executeThread.start(); } public void shutdown() { // 打断主线程 --那么守护进程就被终结了 this.executeThread.interrupt(); } }
我们创建了一个线程服务类,这个服务类由两个方法
[1]开启一个线程
[2]终结一个线程
原理 : 在这个线程类里面有有一个执行线程,在开启的时候会初始化这个线程任务,这个线程任务很简单.
[1] 创建一个子线程,将线程逻辑交给子线程.其中子线程被设置为守护线程.
[2]然后主线程自己阻塞,直到子线程运行完成或者自己的阻塞被打断.
我们的shutdown方法的实现很简单,那就是直接打断执行线程的阻塞状态.一旦执行贤臣被打断,会进入catch语句,语句里面会终结这个函数,那么子线程也被终止了.
五 .总结
现在我们看到线程的终结还需要自己去封装一个服务,到后面我们可以看到大神
李狗的代码,看它是如何解决这种问题的.
这里只是练习一下API而已.