美文网首页
在线程池中寻找堆栈

在线程池中寻找堆栈

作者: 即墨灯火 | 来源:发表于2019-01-02 02:15 被阅读2次

    如果在提交给线程池的任务中抛出了异常,这个异常可能不会打印任何内容,也没有被任何人捕获,形成一个幽灵异常。

    为了避免这种危险情况的发生,有以下解决方式

    1. 使用Future与Callable
    2. 对于Runnable,使用execute方法而非submit方法

    以上两种方式可以获得异常在哪里抛出,但是仍然丢失了一个重要信息:任务的具体提交位置。

    如果想进一步获取上述信息,需要自行扩展ThreadPoolExecutor,使其在调度任务之前,先保存一下提交任务线程的堆栈信息。

    扩展:

    execute与submit的异同

    execute是Executors的接口,submit则是ExecutorService的接口
    对于ThreadPoolExecutor而言,其实现了execute,而sumit方法则继承自抽象类AbstractExecutorService

    对于submit方法

    public Future<?> submit(Runnable task) {
        if (task == null) throw new NullPointerException();
        RunnableFuture<Void> ftask = newTaskFor(task, null);
        execute(ftask); //AbstractExecutorService未实现execute
        return ftask;
    }
    
    /**
    * @throws RejectedExecutionException {@inheritDoc}
     * @throws NullPointerException       {@inheritDoc}
    */
    public <T> Future<T> submit(Runnable task, T result) {
        if (task == null) throw new NullPointerException();
        RunnableFuture<T> ftask = newTaskFor(task, result);
        execute(ftask);
        return ftask;
    }
    
    /**
     * @throws RejectedExecutionException {@inheritDoc}
     * @throws NullPointerException       {@inheritDoc}
     */
    public <T> Future<T> submit(Callable<T> task) {
        if (task == null) throw new NullPointerException();
        RunnableFuture<T> ftask = newTaskFor(task);
        execute(ftask);
        return ftask;
    }
    
    

    可以看到,submit事实上封装了一个Future。

    因此,对于Runnable而言,应当直接使用execute方法,无需经由submit包装。对于希望获得返回值的Callable,则适合使用submit方法。

    参考:
    Java 8 源码
    《实战Java高并发程序设计》
    https://blog.csdn.net/hayre/article/details/53314599

    相关文章

      网友评论

          本文标题:在线程池中寻找堆栈

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