原创JAVA并发编程——Callable和Future源码初探

Posted 陈旭猴

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了原创JAVA并发编程——Callable和Future源码初探相关的知识,希望对你有一定的参考价值。

JAVA多线程实现方式主要有三种:继承Thread类、实现Runnable接口、使用ExecutorService、Callable、Future实现有返回结果的多线程。其中前两种方式线程执行完后都没有返回值,只有最后一种是带返回值的。

 thread和runnable不讨论了。 太多地方可以找到他们的探究了

重点看callable和future,

先上一段代码:

package com.future.chenjun.test;

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 Test {

	public static void main(String[] args) {
		ExecutorService executorService = Executors.newCachedThreadPool();
		MyTask myTask = new MyTask();
		Future<Integer> result = executorService.submit(myTask);
		executorService.shutdown();
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e1) {
			e1.printStackTrace();
		}
		System.out.println("主线程在执行任务");
		try {
			System.out.println("task运行结果" + result.get());
		} catch (InterruptedException e) {
			e.printStackTrace();
		} catch (ExecutionException e) {
			e.printStackTrace();
		}
		
		System.out.println("所有任务执行完毕");

	}

}

class MyTask implements Callable<Integer> {

	@Override
	public Integer call() throws Exception {
		System.out.println("子线程在进行计算");
		Thread.sleep(3000);
		int sum = 0;
		for (int i = 0; i < 100; i++)
			sum += i;
		return sum;
	}

}

  首先分析main()函数第一行 ,这很重要

ExecutorService executorService = Executors.newCachedThreadPool();
自然引出问题1: ExecutorService 本身是一个接口,那
executorService这个引用到底指向了哪个实现类? 这个问题so easy,直接进JDK源码看结果
我们看到实现代码如下:
    public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }

  答案一目了然,根据多态原理无疑这个

ThreadPoolExecutor 就是 ExecutorService的子类。
好,这个问题就此打住,记住结论:
 线索1: ThreadPoolExecutor 就是 ExecutorService的子类。
接下来看main()函数的第三行 : 
Future<Integer> result = executorService.submit(myTask);

  

稍微变一下形式,如下
Future<Integer> result = executorService.submit(new Callable<Integer>(){
    @Override
    public Integer call() throws Exception{
        
    }    
});

  

look ,和如下代码异曲同工

new Thread(new Runnable(){
  //匿名内部类实现XXX
  public void run(){
  }
});

OK 看一下这个submit到底做了什么事

我进ThreadPoolExecutor里面一看,卧槽,发现里面没有submit方法,见鬼了

别急,我翻一下 ThreadPoolExecutor 类声明 

发现如下声明

public class ThreadPoolExecutor extends AbstractExecutorService

  我好奇的打开抽象类AbstractExecutorService.CLASS的源码,莫非这submit藏在这里了

打开了。。。。

终于找到了submit方法,如下

public <T> Future<T> submit(Callable<T> task) {
  

if (task == null) throw new NullPointerException();
    RunnableFuture<T> ftask = newTaskFor(task);
    execute(ftask);
    return ftask;

}

  然后我们自然要搞清楚,这个RunnableFuture是什么鬼,打开它的源码,我们看到:

public interface RunnableFuture<V> extends Runnable, Future<V> {
    /**
     * Sets this Future to the result of its computation
     * unless it has been cancelled.
     */
    void run();
}

  原来如此,他是Runnable, Future<V>的子接口

 

暂时告一段落,理一下思绪

 

 



 

 

以上是关于原创JAVA并发编程——Callable和Future源码初探的主要内容,如果未能解决你的问题,请参考以下文章

JAVA 并发编程-返回运行结果(Callable和Future)

Java Callable并发编程模板

并发编程之Callable异步,Future模式

Java 并发编程——Callable+Future+FutureTask

Java并发编程 - Executor,Executors,ExecutorService, CompletionServie,Future,Callable

Java并发编程:CallableFuture和FutureTask的实现