面试题:如何优雅的停止一个正在运行的java线程

线程状态转换图:

几个容易混淆概念的方法

Thread.sleep()、 Thread.join() 或 Object.wait(),
他们都是阻塞方法并声明抛出 InterruptedException.
当线程调用这些方法进入阻塞状态后, 如果外部调用了interrupt(),
线程进入就绪状态, 并且这些方法抛出InterruptedException异常.

public void Thread.interrupt() // 设置线程的中断状态flag.
public boolean Thread.isInterrupted() // 获取线程的中断状态flag值
public static boolean Thread.interrupted() // 取线程的中断状态flag值,并重置flag值为false.
public final void join() throws InterruptedException  //指的是调用者进入阻塞状态, 而不是线程对象进入阻塞状态, 线程对象继续在执行, 不受影响, 看下面的例子.
public static void yield(); //线程从运行状态, 回到就绪状态.
//demo: join()
public class BottomBarManager {
    private final Object handlePopupMenuAction(int actionCode, Object... args) {
    switch (actionCode) {
            case Actions.MenuContainer.DOWNLOAD: // 下载
                ThreadTest tt = new ThreadTest();
                tt.start();
                try {
                    tt.join();  //当前线程等待tt线程执行完再往下执行
                    //作用是, 当前的UI线程进入阻塞状态, 直到等tt线程执行完再往下继续执行, tt线程该干什么还干什么, 不受影响.
                    //千万不要误理解成tt线程进入了阻塞状态.
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                JLog.i();
            break;


    }


    private class ThreadTest extends Thread {


        @Override
        public void run() {
            try {
                sleep(100000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            JLog.i();
        }
    }


}

中断线程的最佳实践是:  中断 + 条件变量。

最佳模板:

public class BestPractice extends Thread {
    private volatile boolean finished = false;   // ① volatile条件变量
    public void stopMe() {
        finished = true;    // ② 发出停止信号
        interrupt();
    }
    @Override
    public void run() {
        while (!finished) {    // ③ 检测条件变量
        try {
                // do dirty work   // ④业务代码
        } catch (InterruptedException e) {
                if (finished) {
                    return;
                }
                continue;
        }
        }
    }
}

当④处的代码阻塞于wait()或sleep()时,线程不能立刻检测到条件变量。因此②处的代码最好同时调用interrupt()方法。

典型的体现是在volley项目中。
// CacheDispatcher.java
public class CacheDispatcher extends Thread {
    private volatile boolean mQuit = false;


    public void quit() {
        mQuit = true;
        interrupt();
    }


    @Override
    public void run() {
        Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);


        // Make a blocking call to initialize the cache.
        mCache.initialize();


        while (true) {
            try {
                // Get a request from the cache triage queue, blocking until
                // at least one is available.
                final Request<?> request = mCacheQueue.take(); //****** block方法, it throws InterruptedException;
                request.addMarker("cache-queue-take");


                // Attempt to retrieve this item from cache.
                Cache.Entry entry = mCache.get(request.getCacheKey());
                if (entry == null) {
                    request.addMarker("cache-miss");
                    // Cache miss; send off to the network dispatcher.
                    mNetworkQueue.put(request);
                    continue;
                }


                // We have a cache hit; parse its data for delivery back to the request.
                request.addMarker("cache-hit");
                Response<?> response = null;
                try {
                    response = request.parseNetworkResponse(
                            new NetworkResponse(entry.data, entry.responseHeaders));
                } catch (Exception e) {
                    mDelivery.postError(request, new ParseError(e));
                    continue;
                } catch (Error error) {
                    mDelivery.postError(request, new ParseError(error));
                    continue;
                }
                request.addMarker("cache-hit-parsed");


            } catch (InterruptedException e) {
                // We may have been interrupted because it was time to quit.
                if (mQuit) {
                    return;
                }
                continue;
            } catch (OutOfMemoryError error) {
                if (mQuit) {
                    return;
                }
                continue;
            }
        }
    }


}

在quit()代码里, 设置条件变量, 同时调用interrupt()方法.

以后写线程类时, 参考这个模板写就很优雅和规范。

中断是礼貌地请求另一个线程在它愿意并且方便的时候停止它正在做的事情。

喜欢就点个"在看"呗,留言、转发朋友圈

xcbeyond CSDN认证博客专家 架构 Spring Boot Java
疯狂源自梦想,技术成就辉煌!微信公众号:《程序猿技术大咖》号主,专注后端开发多年,拥有丰富的研发经验,乐于技术输出、分享,现阶段从事微服务架构项目的研发工作,涉及架构设计、技术选型、业务研发等工作。对于Java、微服务、数据库、Docker有深入了解,并有大量的调优经验。
相关推荐
<p> <strong><span style="font-size:20px;color:#FF0000;">本课程主要针对计算机相关专业正在做毕设学生与需要项目实战练习Java学习者</span></strong> </p> <p> <span style="color:#FF0000;"><strong><span style="font-size:18px;">1. 包含<span style="color:#FFFF00;background-color:#FF0000;">项目源码、</span><span style="color:#FFFF00;background-color:#FF0000;">项目文档、数据库脚本、软件工具</span>等所有资料</span></strong></span> </p> <p> <span style="color:#FF0000;"><strong><span style="font-size:18px;">2. 手把手带你从零开始部署运行本套系统</span></strong></span> </p> <p> <span style="color:#FF0000;"><strong><span style="font-size:18px;">3. 该项目附带源码资料可作为毕设使用</span></strong></span> </p> <p> <span style="color:#FF0000;"><strong><span style="font-size:18px;">4. 提供技术答疑和远程协助指导</span></strong></span><strong><span style="font-size:18px;"></span></strong> </p> <p> <br /> </p> <p> <span style="font-size:18px;"><strong>项目运行截图</strong></span> </p> <p> <strong><span style="font-size:18px;">1)系统登陆界面</span></strong> </p> <p> <strong><span style="font-size:18px;"><img src="https://img-bss.csdn.net/202002241015433522.png" alt="" /><br /> </span></strong> </p> <p> <strong><span style="font-size:18px;"><strong><span style="font-size:18px;">2)学生模块</span></strong></span></strong> </p> <p> <strong><span style="font-size:18px;"><img src="https://img-bss.csdn.net/202002241015575966.png" alt="" /></span></strong> </p> <p> <strong><span style="font-size:18px;"><strong><span style="font-size:18px;">3)教师模块</span></strong></span></strong> </p> <p> <strong><span style="font-size:18px;"><img src="https://img-bss.csdn.net/202002241016127898.png" alt="" /></span></strong> </p> <p> <strong><span style="font-size:18px;"><strong><span style="font-size:18px;">4)系统管理员</span></strong></span></strong> </p> <p> <strong><span style="font-size:18px;"><img src="https://img-bss.csdn.net/202002241016281177.png" alt="" /></span></strong> </p> <p> <strong><span style="font-size:18px;"><img src="https://img-bss.csdn.net/202002241016369884.png" alt="" /></span></strong> </p> <p> <strong><span style="font-size:18px;"><br /> </span></strong> </p> <p> <strong><span style="font-size:18px;"><strong><span style="font-size:18px;">更多Java毕设项目请关注我毕设系列课程 <a href="https://edu.csdn.net/lecturer/2104">https://edu.csdn.net/lecturer/2104</a></span></strong></span></strong> </p> <p> <strong><span style="font-size:18px;"><br /> </span></strong> </p>
<p> 课程演示环境Windows10  </p> <p> 需要学习<span>Ubuntus</span>系统<span>YOLOv4-tiny</span>同学请前往《<span>YOLOv4-tiny</span>目标检测实战训练自己数据集》 <span></span> </p> <p> <span> </span> </p> <p> <span style="color:#E53333;">YOLOv4-tiny</span><span style="color:#E53333;">来了!速度大幅提升!</span><span></span> </p> <p> <span> </span> </p> <p> <span>YOLOv4-tiny</span>在<span>COCO</span>上性能可达到<span>40.2% AP50, 371 FPS (GTX 1080 Ti)</span>。相较于<span>YOLOv3-tiny</span>,<span>AP</span>和<span>FPS</span>性能有巨大提升。并且,<span>YOLOv4-tiny</span>权重文件只有<span>23MB</span>,适合在移动端、嵌入式设备、边缘计算设备上部署。<span></span> </p> <p> <span> </span> </p> <p> 本课程将手把手地教大家使用<span>labelImg</span>标注和使用<span>YOLOv4-tiny</span>训练自己数据集。课程实战分为两个项目单目标检测(足球目标检测)和多目标检测(足球和梅西同时检测)。<span></span> </p> <p> <span> </span> </p> <p> 本课程<span>YOLOv4-tiny</span>使用<span>AlexAB/darknet</span>,在<span>Windows10</span>系统上做项目演示。包括<span>YOLOv4-tiny</span>网络结构、安装<span>YOLOv4-tiny</span>、标注自己数据集、整理自己数据集、修改配置文件、训练自己数据集、测试训练出网络模型、性能统计<span>(mAP</span>计算<span>)</span>和先验框聚类分析。 <span> </span> </p> <p> <span> </span> </p> <p> 除本课程《<span>Windows</span>版<span>YOLOv4-tiny</span>目标检测实战训练自己数据集》外,本人推出了有关<span>YOLOv4</span>目标检测系列课程。请持续关注该系列其它视频课程,包括<span></span> </p> <p> 《<span>Windows</span>版<span>YOLOv4</span>目标检测实战训练自己数据集》<span></span> </p> <p> 《<span>Windows</span>版<span>YOLOv4</span>目标检测实战人脸口罩佩戴识别》<span></span> </p> <p> 《<span>Windows</span>版<span>YOLOv4</span>目标检测实战中国交通标志识别》<span></span> </p> <p> 《<span>Windows</span>版<span>YOLOv4</span>目标检测原理与源码解析》<span></span> </p> <p> <span> <img alt="" src="https://img-bss.csdnimg.cn/202007061503586145.jpg" /></span> </p> <p> <span><img alt="" src="https://img-bss.csdnimg.cn/202007061504169339.jpg" /><br /> </span> </p>
©️2020 CSDN 皮肤主题: 博客之星2020 设计师:CY__ 返回首页
实付 19.90元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值