java 线程Thread 技术--1.5 Future与Callable

Callable:

从官方文档说起: 通过实现callable 的called 方法可以使一个任务可以返回一个结果以及可能抛出一个异常;

callable 与runnable 是相似的,可以被其他线程潜在的执行,但是runnable不会返回结果总是viod 以及不会抛出检测异常;

/**
 * A task that returns a result and may throw an exception.
 * Implementors define a single method with no arguments called
 * {@code call}.
 *
 * <p>The {@code Callable} interface is similar to {@link
 * java.lang.Runnable}, in that both are designed for classes whose
 * instances are potentially executed by another thread.  A
 * {@code Runnable}, however, does not return a result and cannot
 * throw a checked exception.
 *
 * <p>The {@link Executors} class contains utility methods to
 * convert from other common forms to {@code Callable} classes.

一般我们是这么定义的:

class Task implements Callable<Integer>{

    @Override
    public Integer call() throws Exception {
        
        return 900;
    }
    
}

但是我们如何能够获取到它的返回值?1.5 为我们提供了Future 接口,用于返回一个异步计算的结果,我们这样进行运行:

---线程池里去submit一个callable对象去执行;

public static void main(String[] args) throws Exception, ExecutionException {
        ExecutorService pool = Executors.newFixedThreadPool(2);
        
        //执行callale task,返回future 对象
        Future<Integer> submit = pool.submit(new Task());
        System.out.println(submit);
        Integer integer = submit.get();//obtain thread result ,is block 
        System.out.println(integer);
        System.out.println(submit.isDone()) ;//is finish(trur or false)
        
    }

我们追踪执行callable 的源码:发现内部使用了future实现类.        FutureTask 

 public <T> Future<T> submit(Callable<T> task) {
        if (task == null) throw new NullPointerException();
        RunnableFuture<T> ftask = newTaskFor(task);           //-----------》 这里去new 了一个FutureTask(callable) ,并返回
        execute(ftask);                                 |
        return ftask;                                  |
    }                                            |
                                               |
  protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {      |
        return new FutureTask<T>(callable);              《  ---------
    }

可以看到,其实在 executor 内部运行的是FutureTask ,FutureTask 实现了Future 以及runnable 接口,所以可以获得异步执行的结果;

因为实现了runnable 接口,所以可以这么执行

public static void main(String[] args) throws InterruptedException, ExecutionException {
        
        FutureTask<Integer> task =new FutureTask<>(new Task());
        new Thread(task).start();
        System.out.println(task.get());
    }

也可以直接使用executor 的execute方法:

    public static void main(String[] args) throws InterruptedException, ExecutionException {
        ExecutorService pool = Executors.newFixedThreadPool(2);
        FutureTask<Integer> task =new FutureTask<>(new Task());
        pool.execute(task);
        System.out.println(task.get());
        
        
    }

接下来是一个小练习,比较单线程与多线程之间取1-20000之间的质数数量所花费的时间

package com.java.baseknowledge.concurrent15;

import java.util.ArrayList;
import java.util.List;
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;

/**
 * 计算某一个区域里有多少个质数
 * @author iscys
 *
 */
public class ThreadPool3 {

    
    public static void main(String[] args) throws Exception, ExecutionException {
        long start1 =System.currentTimeMillis();
        List<Integer> zhishu = getZhishu(0,20000);
        System.err.println(zhishu.size());
        System.err.println("单线程"+(System.currentTimeMillis()-start1));
        int thc = Runtime.getRuntime().availableProcessors();
        ExecutorService pool = Executors.newFixedThreadPool(thc*2);
        //lambda 表达式(param)->express
        Future<List<Integer>> ta1 = pool.submit(()->getZhishu(0,8000));
        //lambda 表达式(param)->{statement}
            Future<List<Integer>> ta2 = pool.submit(()->{
            System.out.println(Thread.currentThread().getName());
            List<Integer> ss = getZhishu(8001,13000);
            return ss;
            });
        Future<List<Integer>> ta3 = pool.submit(()->getZhishu(13001,17000));
        Future<List<Integer>> ta4 = pool.submit(()->{

        System.out.println(Thread.currentThread().getName());

        List<Integer> ss = getZhishu(17001,20000);

        return ss;

        });

        long start =System.currentTimeMillis();
        List<Integer> list = ta1.get();
        List<Integer> list2 = ta2.get();
        List<Integer> list3 = ta3.get();
        List<Integer> list4 = ta4.get();
        System.out.println(list.size()+list2.size()+list3.size()+list4.size());
        System.out.println(System.currentTimeMillis()-start);
        pool.shutdown();
    }
    
    static class MyTask implements Callable< List<Integer>>{
        int start ,end;
        MyTask(int start,int end){
            this.start=start;
            this.end=end;
        }
        @Override
        public List<Integer> call() throws Exception {
            // TODO Auto-generated method stub
            return getZhishu(start,end);
        }
        
    }
    
    
    
    
    
    static boolean isZhiShu(int num) {
        
        for(int i=2;i<=num/2;i++) {
            if(num%i==0) {return false;}
        }
        return true;
    }
    
    static List<Integer> getZhishu(int start,int end){
        
        List<Integer> li =new ArrayList<Integer>();
        
        for(int i=start;i<=end;i++) {
            if(isZhiShu(i)) {li.add(i);}
        }
        return li;
    }
}
原创打造,多多指教
原文地址:https://www.cnblogs.com/iscys/p/9721455.html