zoukankan      html  css  js  c++  java
  • JUC-FutureTask

    1. 当我们执行Future future = executorService.submit(myCallable);代码时,我们执行了什么?




    FutureTask 类图

       从类图可以看到,FutureTask实现了两个基类(Future,Runnable);这里实现Future的目的,很明确,因为Future就是代表一个异步任务的未来结果;
    而Runnable,这里是因为JUC线程池通用执行run方法来执行任务的,之所以这么说,有个结论需要记住,线程池执行Callable的时候,其实是通过FutureTask的run方法去执行的;

        //AbstractExecutorService.class
        public <T> Future<T> submit(Callable<T> task) {
            if (task == null) throw new NullPointerException();
            RunnableFuture<T> ftask = newTaskFor(task);
            execute(ftask);
            return ftask;
        }
    
        //AbstractExecutorService.class
        protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
            return new FutureTask<T>(callable);
        }
        //FutureTask.class
        public FutureTask(Callable<V> callable) {
            if (callable == null)
                throw new NullPointerException();
            this.callable = callable;
            this.state = NEW;       // ensure visibility of callable
        }
    

       FutureTask的run代码如下:

        public void run() {
            if (state != NEW ||
                !UNSAFE.compareAndSwapObject(this, runnerOffset,
                                             null, Thread.currentThread()))
                return;
            try {
                Callable<V> c = callable;
                if (c != null && state == NEW) {
                    V result;
                    boolean ran;
                    try {
                        //这里去执行Callable的业务逻辑
                        result = c.call();
                        ran = true;
                    } catch (Throwable ex) {
                        result = null;
                        ran = false;
                        setException(ex);
                    }
                    //执行成功后直接将设置结果
                    if (ran)
                        set(result);
                }
            } finally {
                // runner must be non-null until state is settled to
                // prevent concurrent calls to run()
                runner = null;
                // state must be re-read after nulling runner to prevent
                // leaked interrupts
                int s = state;
                if (s >= INTERRUPTING)
                    handlePossibleCancellationInterrupt(s);
            }
        }
    




    2. 当我们使用FutureTask时,我们想要什么?



       我们首先看看Future的API;

        /**
         * 尝试取消Callable的任务,因为Future是由Callable的索引的,所以功能上是没有问题的
         * mayInterruptIfRunning参数,如果是false,那么如果Callable业务在队列里还没有被执行到,那么任务会被取消
         * 那如果是true呢,那么如果Callable已经在执行中了,那么会将执行线程的中断标识置为true,当然如果业务逻辑不关心isInterrupt,起始对代码执行没有任何影响
         */
        boolean cancel(boolean mayInterruptIfRunning);
    
        /**
         * 是否任务被取消
         */
        boolean isCancelled();
    
        /**
         * 是否任务已经完成
         */
        boolean isDone();
    
        /**
         * 首先这是一个阻塞方法,如果任务还没有被执行完
    	 * 当任务执行完之后,会返回执行结果
         */
        V get() throws InterruptedException, ExecutionException;
    
        /**
         * 有超时时间的get方法
         */
        V get(long timeout, TimeUnit unit)
            throws InterruptedException, ExecutionException, TimeoutException;
    

       显然我们的目标是get()/get(long timeout, TimeUnit unit),当我们需要一个异步执行任务的结果时就可以通过get方法获取;但是缺点是阻塞当前线程,占用资源!

  • 相关阅读:
    sqlserver数据导入问题:报错“对COM组件的调用返回了错误HRESULT E_FAIL”
    删除文件夹提示”该项目不在请确认该项目位置“
    delphi三层DCOM架构
    sqlserver 将店铺表转换成可以用in查询的字符串
    Delphi如何获取一个字符串再另一个字符串中最后一次出现的位置
    c# 通过地址下载流然后保存文件到本地
    使用SQL语句清空数据库所有表的数据
    SqlServer 查询的时候过滤条件有参数导致速度很慢的问题-参数嗅探
    delphi和C# 保存exe文件到数据库
    DELPHI 多线程(TThread类的实现)
  • 原文地址:https://www.cnblogs.com/IC1101/p/12804068.html
Copyright © 2011-2022 走看看