java并发之Future与Callable使用

这篇文章需要大家知道线程、线程池的知识,尤其是线程池。
有的时候我们要获取线程的执行结果,这个时候就需要用到Callable、Future、FutureTask了
先看下Future、Callable接口、RunnableFuture、FutureTask。

Future

Future是一个接口,能够取消任务、获取任务取消状态、获取结果。

package java.util.concurrent;
public interface Future<V> {boolean cancel(boolean mayInterruptIfRunning);boolean isCancelled();/*** Returns {@code true} if this task completed.** Completion may be due to normal termination, an exception, or* cancellation -- in all of these cases, this method will return* {@code true}.** @return {@code true} if this task completed*/boolean isDone();/*** Waits if necessary for the computation to complete, and then* retrieves its result.** @return the computed result* @throws CancellationException if the computation was cancelled* @throws ExecutionException if the computation threw an* exception* @throws InterruptedException if the current thread was interrupted* while waiting*/V get() throws InterruptedException, ExecutionException;V get(long timeout, TimeUnit unit)throws InterruptedException, ExecutionException, TimeoutException;
}

Callable

Callable只有一个功能就是获取结果的V call()。

@FunctionalInterface
public interface Callable<V> {/*** Computes a result, or throws an exception if unable to do so.** @return computed result* @throws Exception if unable to compute a result*/V call() throws Exception;
}

FutureTask

FutureTask是一个实现类,它继承了RunnableFuture,而接口RunnableFuture继承了接口Runable,Future。
因此FutureTask可以通过new Thread(FutureTask task)这样的方式来创建线程。

public class FutureTask<V> implements RunnableFuture<V>

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

通过Future创建线程

获取线程的执行结果,最重要就是FutureTask调用。下面的例子是通过线程池来执行线程,并获取结果 。
1.创建实现Callable接口的类Task,就是返回数字和
2.创建线程池ThreadPoolExecutor,新建Task实例
3.线程池ThreadPoolExecutor执行pool.submit(task)
4.返回了Future result
5.调用Future的get()获取结果
难点是在pool.submit(task)。

package com.java.javabase.thread.future;import lombok.extern.slf4j.Slf4j;import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;/*** @author*/
@Slf4j
public class FutureTest {public static void main(String[] args) {//ExecutorService pool = Executors.newCachedThreadPool();ThreadPoolExecutor pool =new ThreadPoolExecutor(1,1,0, TimeUnit.SECONDS,new ArrayBlockingQueue<Runnable>(1));Task task =new Task();Future<Integer> result=pool.submit(task);/*public <T> Future<T> submit(Callable<T> task) {if (task == null) throw new NullPointerException();RunnableFuture<T> ftask = newTaskFor(task);execute(ftask);return ftask;}*/pool.shutdown();try {log.info("sum {}",result.get());} catch (InterruptedException e) {e.printStackTrace();} catch (ExecutionException e) {e.printStackTrace();}}static class Task implements Callable<Integer> {@Overridepublic Integer call() throws Exception {int sum = 0;for (int i = 0; i < 100; i++) {sum += i;}return sum;}}}

线程池获取结果流程说明

ThreadPoolExecutor.submit方法中执行void execute(Runnable command);
如果了解线程池就应该知道这个方法是能够让command的run方法执行的。实现接口 RunnableFuture的
FutureTask的run方法最后返回线程结果的关键

    public <T> Future<T> submit(Callable<T> task) {if (task == null) throw new NullPointerException();RunnableFuture<T> ftask = newTaskFor(task);execute(ftask);return ftask;}

ThreadPoolExecutor.execute方法

    public void execute(Runnable command) {if (command == null)throw new NullPointerException();int c = ctl.get();if (workerCountOf(c) < corePoolSize) {if (addWorker(command, true))return;c = ctl.get();}if (isRunning(c) && workQueue.offer(command)) {int recheck = ctl.get();if (! isRunning(recheck) && remove(command))reject(command);else if (workerCountOf(recheck) == 0)addWorker(null, false);}else if (!addWorker(command, false))reject(command);}

FutureTask构造器

 public FutureTask(Callable<V> callable) {if (callable == null)throw new NullPointerException();this.callable = callable;this.state = NEW;       // ensure visibility of callable}

FutureTask的run方法
我们创建FutureTask的时候,传入了实现Callable接口的实现类Task,而run()方法中调用了result = c.call();
也就是说FutureTask调用了Callable接口的实现类Task的call方法获取结果,并保存,然后通过对外的get()方法返回。

    public void run() {if (state != NEW ||!UNSAFE.compareAndSwapObject(this, runnerOffset,null, Thread.currentThread()))return;try {Callable<V> c = callable;if (c != null && state == NEW) {V result;boolean ran;try {result = c.call();ran = true;} catch (Throwable ex) {result = null;ran = false;setException(ex);}if (ran)set(result);}} finally {// runner must be non-null until state is settled to// prevent concurrent calls to run()runner = null;// state must be re-read after nulling runner to prevent// leaked interruptsint s = state;if (s >= INTERRUPTING)handlePossibleCancellationInterrupt(s);}}

通过FutureTask创建线程

值得注意的就是获取结果的方式,创建FutureTask,也只能通过FutureTask对象get到结果。
pool.submit(futureTask)返回的Future调用get()返回的是null!

package com.java.javabase.thread.future;import lombok.extern.slf4j.Slf4j;import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;/*** @author*/
@Slf4j
public class FutureTaskTest {public static void main(String[] args) {//ExecutorService pool = Executors.newCachedThreadPool();ThreadPoolExecutor pool =new ThreadPoolExecutor(1,1,0, TimeUnit.SECONDS,new ArrayBlockingQueue<Runnable>(1));Task task =new Task();FutureTask<Integer> futureTask=new FutureTask<Integer>(task);//Future<?> result =pool.submit(futureTask);pool.submit(futureTask);pool.shutdown();try {log.info("sum {}",futureTask.get());} catch (InterruptedException e) {e.printStackTrace();} catch (ExecutionException e) {e.printStackTrace();}Task t2=new Task();FutureTask<Integer> futureTask2=new FutureTask<Integer>(t2);new Thread(futureTask2).start();try {log.info("sum 2 {}",futureTask2.get());} catch (InterruptedException e) {e.printStackTrace();} catch (ExecutionException e) {e.printStackTrace();}}static class Task implements Callable<Integer> {@Overridepublic Integer call() throws Exception {int sum = 0;for (int i = 0; i < 100; i++) {sum += i;}return sum;}}
}

只能通过FutureTask对象get到结果的原因

我就简单强调一点下面的:ftask与task的区别就是获取结果不一致的原因
ftask的run方法调用了对象task的run方法,ftask的get()返回的是null,而实际我们看到自己创建的task的run方法才能返回结果

    public Future<?> submit(Runnable task) {if (task == null) throw new NullPointerException();RunnableFuture<Void> ftask = newTaskFor(task, null);execute(ftask);return ftask;}

转载于:https://www.cnblogs.com/JuncaiF/p/11365176.html

java并发之Future与Callable使用相关推荐

  1. Java 并发之 FutureTask 的基本使用

    为什么80%的码农都做不了架构师?>>>    上次我们说到了 JUC 中的 Future 接口,在最后提到了 FutureTask.CompletionService 等.我们这次 ...

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

    1. Callable 泛型接口,用于获取线程执行完的结果,Callable的声明如下 public interface Callable<V> {// 返回 V 类型的结果V call( ...

  3. Java中的Runnable、Callable、Future、FutureTask

    Java中存在Runnable.Callable.Future.FutureTask这几个与线程相关的类或者接口,在Java中也是比较重要的几个概念,我们通过下面的简单示例来了解一下它们的作用于区别. ...

  4. Java中的Runnable、Callable、Future、FutureTask的区别与示例

    原文地址:http://blog.csdn.net/bboyfeiyu/article/details/24851847 --------------------------------------- ...

  5. 【Java并发】Runnable、Callable、Future、FutureTask

    创建线程的两种方式 直接继承 Thread 实现 Runnable 接口 这两种方式都有一个缺点:在执行完成任务之后,无法直接获取到最后的执行结果.如果需要获取执行结果,就必须通过共享变量或线程通信的 ...

  6. futuretask java 并发请求_【Java并发】Runnable、Callable、Future、FutureTask

    创建线程的两种方式 直接继承 Thread 实现 Runnable 接口 这两种方式都有一个缺点:在执行完成任务之后,无法直接获取到最后的执行结果.如果需要获取执行结果,就必须通过共享变量或线程通信的 ...

  7. 面试:你说你精通Java并发,给我讲讲Java并发之J.U.C

    转载自 面试:你说你精通Java并发,给我讲讲Java并发之J.U.C J.U.C J.U.C即java.util.concurrent包,为我们提供了很多高性能的并发类,可以说是java并发的核心. ...

  8. java.util.concurrent.Future基础

    在此,我开始撰写一系列有关编程语言中的未来概念(也称为promise或delays )的文章,标题为: Back to the Future . 由于对异步,事件驱动,并行和可伸缩系统的需求不断增长, ...

  9. Java多线程(6)--Callable接口创建线程

    与使用Runnable相比, Callable功能更强大些 ①相比run()方法,可以有返回值 ②方法可以抛出异常 ③支持泛型的返回值 ④需要借助FutureTask类,可以获取返回结果 Future ...

最新文章

  1. guava中的Strings
  2. OSChina 周二乱弹 —— 最要命的编程语言?
  3. python精要(69)-turtle(1)
  4. 牛客网暑期ACM多校训练营(第三场)A - PAXM Team(01背包)
  5. POJ - 3694 Network(边双缩点+LCA+并查集优化)
  6. 367. 有效的完全平方数
  7. 【飞秋教程】查找/备份/还原
  8. MySQL 瓶颈分析及优化
  9. Helm 3 完整教程(四):编写第一个 chart
  10. 从留言簿开始,学习MonoRail MVC(三)
  11. 怎么浏览计算机上的驱动程序,怎么查找和更新驱动程序
  12. 12306 抢票 python + selenium + chrome (一) 搜索和参考
  13. Tracking相关的文章
  14. 判断手机号是否是素数
  15. ubuntu系统下的文本编辑器
  16. 前端编写bat批处理文件,实现项目启动功能
  17. 十个英语口语学习网站
  18. STM32F1案例 ST7735 TFT液晶显示屏综合库使用
  19. 什么是项目管理?范围、时间、成本、质量
  20. 360和360极速浏览器无法打开vue项目的问题

热门文章

  1. Java5~11新特性
  2. C 语言 printf 输出详解
  3. Unity 3D 进度条制作
  4. KlayGE C++代码风格指南英文版
  5. WinForm与WebForm调试输出
  6. linux 搭建go编译环境搭建,linux上搭建完整go语言vim开发环境
  7. python docker实战_「docker实战篇」python的docker-docker镜像的创建使用dockerfile(3
  8. 自行搭建嵌入式持续集成工具:从0到1
  9. python安装dlib要cmake,如何使用cmake解决dlib错误?
  10. (21)xilinx PCIE 开发方法(学无止境)