码迷,mamicode.com
首页 > 其他好文 > 详细

FutureTask源码解读

时间:2015-11-11 23:53:17      阅读:245      评论:0      收藏:0      [点我收藏+]

标签:

 

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当中的内部类对象

 

FutureTask源码解读

标签:

原文地址:http://www.cnblogs.com/wuxinliulei/p/4957674.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!