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 ;
} }

但是我们如何能够获取到它的返回值?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;
}
}

java 线程Thread 技术--1.5 Future与Callable的更多相关文章

  1. java 线程Thread 技术--1.5 Executor Executors,ThreadPool,Queue

    Executors : Executors ,就是一个线程工具类:大部分操作线程的方法,都可以在这个工具类中就行创建,执行,调用一些线程的方法: Executor : 用于执行和提交一个runnabl ...

  2. java 线程Thread 技术--线程状态与同步问题

    线程技术第三篇: 线程的状态: 1. 创建状态: 当用new 操作符创建一个新的线程对象时,该线程就处于创建状态,系统不为它分配资源 2.可运行状态:当线程调用start 方法将为线程分配必须的系统资 ...

  3. java 线程Thread 技术--volatile关键字

    java 语言中允许线程访问共享变量,为了保证共享变量能被准确和一致的更新,Java 语言提供了volatile 关键字,也就是我们所说的内存一致性: 问题抛出:(尝试去运行下面代码,以及将volat ...

  4. java 线程Thread 技术--1.5Lock 与condition 演示生产者与消费模式

    在jdk 1.5 后,Java 引入了lock 锁来替代synchronized ,在使用中,lock锁的使用更加灵活,提供了灵活的 api ,不像传统的synchronized ,一旦进入synch ...

  5. java 线程Thread 技术--方法演示生产与消费模式

    利用wait 与notifyAll 方法进行演示生产与消费的模式的演示,我们两个线程负责生产,两个线程消费,只有生产了才能消费: 在effective Java 中有说过: 1. 在Java 中 ,使 ...

  6. java 线程Thread 技术--线程创建源码解释

    永远不要忘记最基础的东西,只有把最基础的知识打牢靠,才能够使你走的更远,我将从今天开始,进行线程知识的回顾,一些常用知识点,以及java1.5 引入的并发库,进行详细的讲解与总结 创建线程的目的是为了 ...

  7. java 线程Thread 技术--线程方法详解

    Thread 类常用的方法与Object类提供的线程操作方法:(一个对象只有一把锁

  8. java 线程Thread 技术--创建线程的方式

    在第一节中,对线程的创建我们通过看文档,得知线程的创建有两种方式进行实现,我们进行第一种方式的创建,通过继承Thread 类 ,并且重写它的run 方法,就可以进行线程的创建,所有的程序执行都放在了r ...

  9. java线程池技术(二): 核心ThreadPoolExecutor介绍

    版权声明:本文出自汪磊的博客,转载请务必注明出处. Java线程池技术属于比较"古老"而又比较基础的技术了,本篇博客主要作用是个人技术梳理,没什么新玩意. 一.Java线程池技术的 ...

随机推荐

  1. 盒子变形-盒子加padding后 变形问题,

    1. box-sizing: content-box: 影响: 加了内外边距后整个盒子的大小同步改变 2.box-sizing: border-box;影响:加了边距后整个盒子大小不受影响 boots ...

  2. C++复习:纯虚函数和抽象类

    纯虚函数和抽象类 1基本概念 2抽象类案例   3抽象类在多继承中的应用 C++中没有Java中的接口概念,抽象类可以模拟Java中的接口类.(接口和协议) 3.1有关多继承的说明 工程上的多继承 被 ...

  3. while 循环居然可以用else

    while 循环居然可以用else python 3 while a<50: print a a=a+1 else: print"over."

  4. 在系统中使用Bean Validation验证参数

    转自:http://www.importnew.com/18561.html 为什么要使用Bean Validation?  当我们实现某个接口时,都需要对入参数进行校验.例如下面的代码 1 2 3 ...

  5. 分页插件 PageHelper

    一步:pom 依赖 二步:controller层 三步:id调用了三个包,org.n3r.idworker的包,这是一体的不用修改,调用即可生成,电商,腾讯都会用这个 , 前三位是年日 四步:serv ...

  6. ArcGIS 10安装及破解

    1.下载 ArcGIS 10 安装程序及破解文件后面提供电驴的下载地址(可以使用迅雷.QQ旋风等下载工具下载),下载文件是一个光盘镜像文件:? ArcGIS_Desktop10_122519.iso. ...

  7. Cascade Classifier Training 没有基础也会目标检测啦

    Cascade Classifier Training 具体自己看: http://docs.opencv.org/2.4.13.2/doc/user_guide/ug_traincascade.ht ...

  8. hdu1042-N!-(java大数)

    题目:求n!(0<=n<=10000) import java.math.BigInteger;//操作大整数 import java.math.BigDecimal;//操作大小数 im ...

  9. ASP.NET 三级联动

    三级联动就是用三个下拉列表框DropDownList,每个里面添加相应的东西,在第一个列表框中选择一个值,第二三个列表框都会根据第一个选择进行相应的变化,在第二个列表框中选择一个值,第三个列表框也会根 ...

  10. Java闰年的计算,Calendar的用法

    Java闰年的计算,Calendar的用法 代码如下: package com.aaa.zuoye; import java.text.ParseException; import java.util ...