zoukankan      html  css  js  c++  java
  • FutureTask源码解读

    import java.util.concurrent.Callable;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.Future;
    
    public class TestFuture
    {
    
    	public static void main(String[] args) throws InterruptedException, ExecutionException
    	{
    		final ExecutorService executor = Executors.newCachedThreadPool();
    		final Future<String> future = executor.submit(new CallableTest());
    
    		System.out.println("continue working");
    
    		System.out.println(future.get());
    	}
    }
    
    class CallableTest implements Callable<String>
    {
    
    	@Override
    	public String call() throws Exception
    	{
    		Thread.sleep(5000);
    		return "Hello World!";
    	}
    
    }
    

    上面的代码很简单,定义了一个Callable对象,利用ExecutorService线程池将Callable对象提交到线程池当中去执行。

    本文要详细讲述的就是JDK中怎么通过Future对象来等待任务结果并阻塞线程(get())、取消任务等对任务线程的控制。

    ---------------------------------------------------------------------------------------------------------------

    当将Callable对象、Runnable对象通过ExecutorService当中的submit方法提交到线程池当中的时候,会返回一个Future<T>的对象,通过Future<T>对象可以拿到相应的返回结果

    1)提交任务后,主线程是继续向下执行的,因为任务被异步线程去执行了

    2)当任务仍未执行完的时候,如果任何一个线程调用Future<T>对象的get()方法想获取返回值得时候,都会将线程阻塞,等任务执行完毕之后,返回结果,线程被唤醒重新执行。

    3)这提供了一种共享锁的模型,很多线程都可以通过同一个Future<T>对象阻塞在一个条件上

    --------------------------------这种多个线程阻塞和唤醒是怎么做到的呢?----------------------

    package java.util.concurrent;
    
    public interface Future<V> {
    
        boolean cancel(boolean mayInterruptIfRunning);
      
        boolean isCancelled();
    
        V get() throws InterruptedException, ExecutionException;
    
        V get(long timeout, TimeUnit unit)
            throws InterruptedException, ExecutionException, TimeoutException;
    }
    

    我们看到Future<V>其实只是一个接口,那么他的实现在哪里呢?

    -------------------------------------------

    在ExecutorService的实现类AbstractExeccutorService当中的submit(Callable<T> callable)

    实现中(submit的作用就是提交一个有返回值的任务给线程池,并且返回一个Future对象来处理返回结果)

        public <T> Future<T> submit(Callable<T> task) {
            if (task == null) throw new NullPointerException();
            RunnableFuture<T> ftask = newTaskFor(task);
            execute(ftask);
            return ftask;
        }

     

    看到返回的是一个RunnableFuture对象,这个对象实现了Runnable和Future的接口

    protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
            return new FutureTask<T>(callable);
        }
    

    看到返回的是FutureTask对象其实,包裹了Callable对象

    这样其实就可以理解了,FutureTask对象实现了Runnable和Future接口,将FutureTask这个Runnable对象丢到Execcutor线程池当中异步执行(execute(ftask))

    最终执行FutureTask对象的run方法,可想而已,在run方法中调用了Callable对象的call方法,并且将返回值赋值给FutureTask对象的成员变量以便get方法获取。

    --------------------------------------------

     public void run() {
            sync.innerRun();
        }
    

    果然我们在FutureTask的run方法中看到调用了Sync对象的innerRun()方法

            void innerRun() {
                if (!compareAndSetState(READY, RUNNING))
                    return;
    
                runner = Thread.currentThread();
                if (getState() == RUNNING) { // recheck after setting thread
                    V result;
                    try {
                        result = callable.call();
                    } catch (Throwable ex) {
                        setException(ex);
                        return;
                    }
                    set(result);
                } else {
                    releaseShared(0); // cancel
                }
            }
    

      private final class Sync extends AbstractQueuedSynchronizer

    Sync对象是在FutureTask当中的内部类对象

  • 相关阅读:
    ASE19 团队项目 模型组 scrum report集合
    ASE19团队项目alpha阶段model组 scrum2 记录
    ASE19团队项目alpha阶段model组 scrum1 记录
    ASE第二次结对编程——Code Search
    jdk中集成的jre和单独安装的jre有什么区别?
    window, linux, mac 比较文件和文件夹的区别
    Java 调用python、ruby 等脚本引擎
    微软软件工程 第一周博客作业
    绩效考核(2018.5.28~2018.6.3)
    数据库需求文档
  • 原文地址:https://www.cnblogs.com/wuxinliulei/p/4957674.html
Copyright © 2011-2022 走看看