线程取消

使用volatile域保存状态


    private static class MyThread extends Thread {

        private volatile boolean isStop = false;

        @Override
        public void run() {
            try {
                while (!isStop) {
                    // ...
                    Thread.sleep(1000);
                }
            } catch (InterruptedException e) {
                // ...传递异常或者恢复中断,否则上层应用感知不到状态的变化,有可能导致程序的错误
            }
        }

        public void cancel() {
            isStop = true;
        }
    }
  1. 每次退出检测需要耗费一定的时间
  2. 如果在while内线程被阻塞了,线程可能永远无法结束

线程中断

  1. 每个线程都有一个boolean类型的中断状态
  2. interrupt()方法能够中断目标线程,isInterrupted()方法能够返回目标线程的中断状态,interrupted()方法能够清除线程的中断状态,并且返回之前的状态值,清除状态唯一的方法。
  3. 当线程处于阻塞(join,sleep,wait,sleep)的状态下,中断响应:清除中断的标记,抛出InterruptedException
  4. 当线程处于非阻塞的状态下,中断响应:保持中断状态
  5. 使用interrupted()方法一定要小心,因为会导致中断状态清除,应对方法,手动抛出InterruptedException或者调用interrupt()方法进行恢复中断
  6. 通常中断是实现线程取消的最合理的方法
    private static class MyThread extends Thread {

        @Override
        public void run() {
            try {
                while (!Thread.currentThread().isInterrupted()) {
                    // ...
                    Thread.sleep(1000);
                }
            } catch (InterruptedException e) {
                // ...传递异常或者恢复中断,否则上层应用感知不到状态的变化,有可能导致程序的错误
            }
        }

        public void cancel() {
            interrupt();
        }
    }

使用Future进行线程取消

        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                // ...
            }
        };
        ExecutorService executor = Executors.newCachedThreadPool();
        Future<?> task = executor.submit(runnable);
        try {
            // 定时长线程执行
            task.get(1000, TimeUnit.MICROSECONDS);
        } catch (InterruptedException e) {
            e.printStackTrace();
            // 阻塞时出现中断
        } catch (ExecutionException e) {
            e.printStackTrace();
            // 线程过程中执行出现异常
        } catch (TimeoutException e) {
            e.printStackTrace();
            // 接下来线程会被取消
        } finally {
            // 如果任务已经结束,取消线程不会带来任何影响
            // 如果你不需要知道任务的结果,也可直接取消
            task.cancel(true);
        }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
安全可靠的线程取消方式有以下几种: 1. 通过设置标志位取消线程:在线程函数中设置一个标志位,标识线程是否需要退出。在主线程或其他线程中设置该标志位,当线程检测到该标志位时,主动退出线程函数。这种方式需要线程函数自己检测退出标志,可以在合适的地方进行资源释放,避免资源泄露。 2. 使用 std::thread::joinable() 函数检测线程是否可 join:可以使用 std::thread::joinable() 函数检测线程是否处于可 join 状态,如果可 join,则可以使用 join() 函数等待线程执行完成。如果线程已经执行完毕或者已经分离,则不需要 join(),也不需要进行取消操作。 3. 使用 condition_variable 等待线程执行完成:可以使用 condition_variable 等待线程执行完成,当需要取消线程时,可以调用 notify_all() 函数通知线程退出。这种方式需要在线程函数中使用 unique_lock 来保护共享资源,以避免竞争条件和死锁等问题。 4. 使用 atomic 变量取消线程:可以使用 atomic 变量来控制线程的执行,当需要取消线程时,设置 atomic 变量的值,线程检测到该变量的值后退出。这种方式需要在线程函数中使用 atomic_load() 函数来读取变量的值,以确保线程安全。 需要注意的是,线程取消操作可能会导致一些未知的问题,比如内存泄露、死锁等。因此,在设计程序时应该尽量避免使用线程取消操作,而是使用线程同步和协作来控制线程的执行。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值