• 【原创】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>的子接口

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



    
    
  • 相关阅读:
    Spark Scala 读取GBK文件的方法
    Mac OS X 系统下自带的文本文件格式转换工具iconv
    报到
    java 字符串中含有双引号" "与单引号' '问题
    div1嵌套div2,div2居中的解决办法
    ionic4 创建 angular项目 ReactNative下载第三方库出错解决Error: EPERM: operation not permitted, rename
    ionic+cordova 创建项目+打包
    jxl读取excel文件异常:Unable to recognize OLE stream 的解决方法
    学习 javascript (一)javascript 简介
    学习 JavaScript (四)核心概念:操作符
  • 原文地址:https://www.cnblogs.com/ChenJunHacker/p/5630591.html
Copyright © 2020-2023  润新知