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; } }
原创打造,多多指教