上次介绍了Callable实现多线程的方法。现在介绍和Callable搭配的类。上一篇只是简单的用Callable做了一个demo。

一、Future

1.关于callable和runable的区别(上次已经介绍)

  • Callable可以在任务结束的时候提供一个返回值Future对象,Runnable无法提供这个功能

  • Callable的call方法分可以抛出异常,而Runnable的run方法不能抛出异常。

  • Callable规定的方法是call(),而Runnable规定的方法是run().

2.Future介绍

Future就是对于具体的Runnable或者Callable任务的执行结果进行取消、查询是否完成、获取结果。必要时可以通过get方法获取执行结果,该方法会阻塞直到任务返回结果。

Future类位于java.util.concurrent包下,它是一个接口:

public interface Future<V> {
    boolean cancel(boolean mayInterruptIfRunning);
    boolean isCancelled();
    boolean isDone();
    V get() throws InterruptedException, ExecutionException;
    V get(long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException;
}

在Future接口中声明了5个方法,下面依次解释每个方法的作用:

  • cancel方法用来取消任务,如果取消任务成功则返回true,如果取消任务失败则返回false。参数mayInterruptIfRunning表示是否允许取消正在执行却没有执行完毕的任务,如果设置true,则表示可以取消正在执行过程中的任务。如果任务已经完成,则无论mayInterruptIfRunning为true还是false,此方法肯定返回false,即如果取消已经完成的任务会返回false;如果任务正在执行,若mayInterruptIfRunning设置为true,则返回true,若mayInterruptIfRunning设置为false,则返回false;如果任务还没有执行,则无论mayInterruptIfRunning为true还是false,肯定返回true。
  • isCancelled方法表示任务是否被取消成功,如果在任务正常完成前被取消成功,则返回 true。
  • isDone方法表示任务是否已经完成,若任务完成,则返回true;
  • get()方法用来获取执行结果,这个方法会产生阻塞,会一直等到任务执行完毕才返回;
  • get(long timeout, TimeUnit unit)用来获取执行结果,如果在指定时间内,还没获取到结果,就直接返回null。

  也就是说Future提供了三种功能:

  1)判断任务是否完成;

  2)能够中断任务;

  3)能够获取任务执行结果。

  因为Future只是一个接口,所以是无法直接用来创建对象使用的,因此就有了FutureTask。

3.测试

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

结果:

子线程在进行计算
主线程在执行任务
task运行结果4950
所有任务执行完毕

二、FutureTask

1.FutureTask的实现

public class FutureTask<V> implements RunnableFuture<V>

FutureTask类实现了RunnableFuture接口,我们看一下RunnableFuture接口的实现:

public interface RunnableFuture<V> extends Runnable, Future<V> {  void run();  }

可以看出RunnableFuture继承了Runnable接口和Future接口,而FutureTask实现了RunnableFuture接口。

也就是说:

FutureTask实现了Runnable,因此它既可以通过Thread包装来直接执行,也可以提交给ExecuteService来执行。 
FutureTask实现了Futrue可以直接通过get()函数获取执行结果,该函数会阻塞,直到结果返回。

FutureTask提供了2个构造器:

public FutureTask(Callable<V> callable) {}
public FutureTask(Runnable runnable, V result) {}

FutureTask是Future接口的一个实现类(唯一的实现类)。

2.测试

public class FutureTaskTest {
    public static void main(String[] args) {
        ExecutorService executor = Executors.newCachedThreadPool();
        newTask task = new newTask();
        FutureTask<Integer> futureTask = new FutureTask<Integer>(task);
        executor.submit(futureTask);
        executor.shutdown();
        try {
            Thread.sleep(1000);
        catch (InterruptedException e1) {
            e1.printStackTrace();
        }
 
        System.out.println("主线程在执行任务");
 
        try {
            System.out.println("task运行结果" + futureTask.get());
        catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
 
        System.out.println("所有任务执行完毕");
    }
}
 
class newTask 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;
    }
 
}

结果:

子线程在进行计算
主线程在执行任务
task运行结果4950
所有任务执行完毕

Future和FutureTask的更多相关文章

  1. Java并发编程:Callable、Future和FutureTask

    作者:海子 出处:http://www.cnblogs.com/dolphin0520/ 本博客中未标明转载的文章归作者海子和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置 ...

  2. Java多线程21:多线程下的其他组件之CyclicBarrier、Callable、Future和FutureTask

    CyclicBarrier 接着讲多线程下的其他组件,第一个要讲的就是CyclicBarrier.CyclicBarrier从字面理解是指循环屏障,它可以协同多个线程,让多个线程在这个屏障前等待,直到 ...

  3. Java并发:Callable、Future和FutureTask

    Java并发编程:Callable.Future和FutureTask 在前面的文章中我们讲述了创建线程的2种方式,一种是直接继承Thread,另外一种就是实现Runnable接口. 这2种方式都有一 ...

  4. Runnable、Callable、Future和FutureTask用法

    http://www.cnblogs.com/dolphin0520/p/3949310.html java 1.5以前创建线程的2种方式,一种是直接继承Thread,另外一种就是实现Runnable ...

  5. Callable、Future和FutureTask区别

    在前面的文章中我们讲述了创建线程的2种方式,一种是直接继承Thread,另外一种就是实现Runnable接口. 这2种方式都有一个缺陷就是:在执行完任务之后无法获取执行结果. 如果需要获取执行结果,就 ...

  6. Java并发编程:Callable、Future和FutureTask的实现

    启动线程执行任务,如果需要在任务执行完毕之后得到任务执行结果,可以使用从Java 1.5开始提供的Callable和Future 下面就分析一下Callable.Future以及FutureTask的 ...

  7. (转)Java并发编程:Callable、Future和FutureTask

    Java并发编程:Callable.Future和FutureTask 在前面的文章中我们讲述了创建线程的2种方式,一种是直接继承Thread,另外一种就是实现Runnable接口. 这2种方式都有一 ...

  8. java多线程系列(七)---Callable、Future和FutureTask

    Callable.Future和FutureTask 前言:如有不正确的地方,还望指正. 目录 认识cpu.核心与线程 java多线程系列(一)之java多线程技能 java多线程系列(二)之对象变量 ...

  9. [转载] Java并发编程:Callable、Future和FutureTask

    转载自http://www.cnblogs.com/dolphin0520/p/3949310.html 在前面的文章中我们讲述了创建线程的2种方式,一种是直接继承Thread,另外一种就是实现Run ...

  10. 【Java并发编程】Callable、Future和FutureTask的实现

    启动线程执行任务,如果需要在任务执行完毕之后得到任务执行结果,可以使用从Java 1.5开始提供的Callable和Future 下面就分析一下Callable.Future以及FutureTask的 ...

随机推荐

  1. Java基础-使用Idea进行远程调试

    Java基础-使用Idea进行远程调试 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任.

  2. 卸载并安装指定版本Angular CLI

    1.卸载之前的版本 npm uninstall -g @angular/cli 2.清除缓存,确保卸载干净 npm cache clean 3.检查是否卸载干净 输入命令 ng -v 若显示comma ...

  3. git的权威指南

    CHENYILONG 博客 git的权威指南 全屏 © chenyilong.本站由Postach.io 博客

  4. 蓝桥杯 问题 1110: 2^k进制数 (排列组合+高精度巧妙处理)

    题目链接 题目描述 设r是个2^k 进制数,并满足以下条件: (1)r至少是个2位的2^k 进制数. (2)作为2^k 进制数,除最后一位外,r的每一位严格小于它右边相邻的那一位. (3)将r转换为2 ...

  5. 爬虫笔记之刷小怪练级:yymp3爬虫(音乐类爬虫)

    一.目标 爬取http://www.yymp3.com网站歌曲相关信息,包括歌曲名字.作者相关信息.歌曲的音频数据.歌曲的歌词数据. 二.分析 2.1 歌曲信息.歌曲音频数据下载地址的获取 随便打开一 ...

  6. CentOS 无法通过 yum 安装新版 nodejs 解决办法(安装的还是老版的)

    官网安装说明:CentOS 安装 nodejs 第一步: curl --silent --location https://rpm.nodesource.com/setup_10.x | sudo b ...

  7. 【API】网络编程模型、多线程

    1.网络通信编程 1)网络通信模型基础知识 TCP Server: WSAStartup() socket() bind() linsten() accept() send/recv() closes ...

  8. vim下如何去掉windows编辑的文件中的^M

    可以去掉^M, 例如: 在终端下敲命令: dos2unix a.c 直接转换成unix格式,这样就可以去掉^M •$dos2unix filename •vim filename :%s/^M$//g ...

  9. C# UDP广播消息

    首先是发送端: /// <summary> /// 发送UDP消息 /// </summary> /// <param name="msg">消 ...

  10. Flask源码解析:Flask应用执行流程及原理

    WSGI WSGI:全称是Web Server Gateway Interface,WSGI不是服务器,python模块,框架,API或者任何软件,只是一种规范,描述服务器端如何与web应用程序通信的 ...