美文网首页
线程池任务超时

线程池任务超时

作者: 多关心老人 | 来源:发表于2019-10-14 16:52 被阅读0次

往线程池提交(submit)任务,会把任务封装成FutureTask然后提交,返回future。
如果要取消任务,用future.cancel(), 在任务的状态不是NEW的情况下,cancel()方法没用,因为其他状态都表示任务已经完成或取消了。

private static final int NEW          = 0;
    private static final int COMPLETING   = 1;
    private static final int NORMAL       = 2;
    private static final int EXCEPTIONAL  = 3;
    private static final int CANCELLED    = 4;
    private static final int INTERRUPTING = 5;
    private static final int INTERRUPTED  = 6;

注意:任务执行中的状态也是NEW。

如果任务还没开始,那么cancel后这个任务永不运行(周期性的任务以后不再运行)。如果任务已经开始执行,futureTask中会保持一个执行线程runner的引用,调用runner.interrupt(), 我们知道interrupt()只会让处于阻塞状态的线程抛出InterruptedException异常(中断状态清除),否则只会设置中断状态。

    public boolean cancel(boolean mayInterruptIfRunning) {
        if (!(state == NEW &&
              UNSAFE.compareAndSwapInt(this, stateOffset, NEW,
                  mayInterruptIfRunning ? INTERRUPTING : CANCELLED)))
            return false;
        try {    // in case call to interrupt throws exception
            if (mayInterruptIfRunning) {
                try {
                    Thread t = runner;
                    if (t != null)
                        t.interrupt();
                } finally { // final state
                    UNSAFE.putOrderedInt(this, stateOffset, INTERRUPTED);
                }
            }
        } finally {
            finishCompletion();
        }
        return true;
    }

由于Thread.interrupt()不能真正中断线程,因此我们要在任务的run()中不时的去轮询Thraed.isInterrupted()来看任务是不是被取消了(当然也不是很准确,因为线程也可能是被别的原因中断,而不是future.cancel(),可以在future.cancel()的时候设置任务的状态,轮询这个状态就能判断任务是不是被取消了)。

被取消的任务调用future.get()会抛出CancellationException。

 private V report(int s) throws ExecutionException {
        Object x = outcome;
        if (s == NORMAL)
            return (V)x;
        if (s >= CANCELLED)
            throw new CancellationException();
        throw new ExecutionException((Throwable)x);
    }

前面说了,取消任务通过future.cancel(),那么谁负责去调这个方法呢?主线程和任务执行线程都不合适去调,这里我是通过额外提交一个定时任务去实现,即在提交任务的时候,再提交一个延时的定时任务,延后的时间就是任务的超时时间。这样就会有2个任务了,可能会造成延时任务没执行或别的原因导致没取消掉或取消时间不准。

如果大家有更好的实现方式,也可以留言讨论。

相关文章

  • 线程池任务超时

    往线程池提交(submit)任务,会把任务封装成FutureTask然后提交,返回future。如果要取消任务,用...

  • 使用ExecutorService,提交任务卡死?

    问题描述 最近在使用ExecutorService线程池提交任务,发现任务一直不执行,设置了超时时间,也会抛出超时...

  • 034 如何确保线程池不丢失任务?

    如何确保线程池不丢失任务? 加快消费速度减少任务排队,降低丢失风险; 利用钩子方法,当任务超时时,任务重新入队,注...

  • pthread 创建的动态线程池

    组织结构: 1,缓存工作的任务池,任务节点 2,存储工作线程的池,线程节点 3,任务池投递到工作线程的线程 4,工...

  • java线程池

    线程VS线程池 普通线程使用 创建线程池 执行任务 执行完毕,释放线程对象 线程池 创建线程池 拿线程池线程去执行...

  • 线程池

    线程池的实现原理当向线程池提交一个任务之后,线程池是如何处理这个任务呢?(1)线程池判断核心线程池里的线程是否都在...

  • 一篇文章搞懂线程池

    线程池 什么使用使用线程池? 单个任务处理时间比较短 需要处理的任务数量很大 线程池优势 重用存在的线程,减少线程...

  • 08 线程池

    1 线程池概述 1.1 什么是线程池 线程池就是提前创建若干个线程,如果有任务需要处理,线程池里的线程就会处理任务...

  • 线程池

    线程池ThreadPoolExecutor 运行步骤:1,任务进来 新建核心线程执行任务 直到核心线程池占满 ...

  • 线程池源码分析

    线程池源码分析 在线程池执行任务的时候,都是主线程(可能是tomcat线程),将任务放到线程池中,再执行线程池的e...

网友评论

      本文标题:线程池任务超时

      本文链接:https://www.haomeiwen.com/subject/qlpzectx.html