java-Callable与Future的应用

news/2025/5/30 17:54:52

目录

 

一、引言

二、Callable与Runnable

三.Future

三、Callable与Runnable应用

四、FutureTask

五、CompletionService


一、引言

在前面的文章中我们讲述了创建线程的2种方式,一种是直接继承Thread,另外一种就是实现Runnable接口。这2种方式都有一个缺陷就是:在执行完任务之后无法获取执行结果。如果需要获取执行结果,就必须通过共享变量或者使用线程通信的方式来达到效果,这样使用起来就比较麻烦。而自从Java 1.5开始,就提供了Callable和Future,通过它们可以在任务执行完毕之后得到任务执行结果。

本篇说明的是Callable和Future,它俩很有意思的,一个产生结果,一个拿到结果。 Callable接口类似于Runnable,从名字就可以看出来了,但是Runnable不会返回结果,并且无法抛出返回结果的异常,大一而Callable功能更强些,被线程执行后,可以返回值,这个返回值可以被Future拿到,也就是说,Future可以拿到异步执行任务的返回值。

二、Callable与Runnable

java.lang.Runnable是一个接口,在它里面只声明了一个run()方法,由于run()方法返回值为void类型,所以在执行完任务之后无法返回任何结果。

public interface Runnable {public abstract void run();
}

Callable位于java.util.concurrent包下,它也是一个接口,在它里面也只声明了一个方法call(),这是一个泛型接口,call()函数返回的类型就是传递进来的V类型。

public interface Callable<V> {V call() throws Exception;
}

Callable要采用ExecutorSevice的submit方法提交,而不是execute方法,因为execute方法没有返回值,在ExecutorService接口中有若干个submit方法的重载版本。

<T> Future<T> submit(Callable<T> task);
<T> Future<T> submit(Runnable task, T result);
Future<?> submit(Runnable task);

第一个submit方法里面的参数类型就是Callable。

一般情况下我们使用第一个submit方法和第三个submit方法,第二个submit方法很少使用。

三.Future

Future是一个接口,它可以对Callable任务的执行结果进行操作。可以说Future提供了三种功能:判断任务是否完成;能够中断任务;能够获取任务执行结果。

    boolean cancel(boolean mayInterruptIfRunning);boolean isCancelled();boolean isDone();V get() throws InterruptedException, ExecutionException;V get(long timeout, TimeUnit unit)throws InterruptedException, ExecutionException, TimeoutException;

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。

三、Callable与Runnable应用

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;public class AtomicIntegerFieldUpdaterTest {public static <T> void main(String[] args) {ExecutorService newFixedThreadPool = Executors.newSingleThreadExecutor();Future<String> submit = newFixedThreadPool.submit(new Callable<String>() {@Overridepublic String call() throws Exception {// TODO Auto-generated method stubreturn "我是生产的结果";}});try {System.out.println("我来拿结果了:"+submit.get());} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (ExecutionException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}

 

四、FutureTask

FutureTask实现了两个接口,Runnable和Future,所以它既可以作为Runnable被线程执行,又可以作为Future得到。

使用实例:

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.FutureTask;public class AtomicIntegerFieldUpdaterTest {public static <T> void main(String[] args) throws InterruptedException {ExecutorService es = Executors.newSingleThreadExecutor();System.out.println("主线程do something");FutureTask<Integer> futuretask = new FutureTask<>(new Callable<Integer>() {public Integer call() throws Exception {Thread.sleep(2000);System.out.println("子线程执行耗时操作");return 100;}});es.execute(futuretask);System.out.println("我不管子线程,我需要干点其他事,主线程继续do something");try {System.out.println("执行结果为" + futuretask.get());} catch (ExecutionException e) {// TODO Auto-generated catch blocke.printStackTrace();}}
}

五、CompletionService

CompletionService接口用于提交一组Callable任务,其take方法返回已完成的一个Callable任务对应的Future对象。

import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;public class CallableAndFuture {public static void main(String[] args) {		ExecutorService threadPool2 = Executors.newFixedThreadPool(10);	CompletionService<Integer> completionService = new ExecutorCompletionService<Integer>(threadPool2);//向CompletionService中提交10个任务for(int i=1;i<=10;i++){final int sequence = i;//记录任务序号completionService.submit(new Callable<Integer>(){public Integer call() throws Exception {//每个任务设置随机耗时时间Thread.sleep(new Random().nextInt(5000));return sequence;//返回的是当前任务的序号}});}//获取结果for (int i = 0; i < 10; i++) {try {System.out.println(completionService.take().get());} catch (InterruptedException e) {e.printStackTrace();} catch (ExecutionException e) {e.printStackTrace();}}}
}

 

文章来源:https://blog.csdn.net/yucaixiang/article/details/89241435
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:https://dhexx.cn/news/show-588022.html

相关文章

Java集合框架HashSet和HashMap源码剖析

原文地址:点击阅读全文围观总体介绍之所以把HashSet和HashMap放在一起讲解&#xff0c;是因为二者在Java里有着相同的实现&#xff0c;前者仅仅是对后者做了一层包装&#xff0c;也就是说HashSet里面有一个HashMap&#xff08;适配器模式&#xff09;。因此本文将重点分析HashM…

DOM概览

node节点&#xff0c;一共有10个重要属性&#xff1a;nodetype&#xff0c;得到1-12的数字&#xff0c;对应着不同的节点类型&#xff0c;nodeName&#xff0c;得到节点名称nodeValue&#xff0c;得到节点值&#xff0c;string类型&#xff0c;不一定存在&#xff0c;没有值的时…

java并发-ReentrantReadWriteLock读写锁

一、概念 Java常见的多是排他锁&#xff0c;这些锁在同一时刻只允许一个线程进行访问&#xff0c;而读写锁在同一时刻可以允许多个读线程访问&#xff0c;但是在写线程访问时&#xff0c;所有的读线程和其他写线程均被阻塞。读写锁维护了一对锁&#xff0c;一个读锁和一个写锁…

Java编程常见坑汇总(下)

原文地址:点击阅读全文围观30.对List的误用建议下列场景用Array来替代List:1.list长度固定&#xff0c;比如一周中的每一天2.对list频繁的遍历&#xff0c;比如超过1w次3.需要对数字进行包装(主要JDK没有提供基本类型的List)比如下面的代码。错误的写法&#xff1a;List<Int…

对于后台特殊功能问题思路

1.搜索功能从表单传递对应的搜索数据传入后台&#xff0c;在后台进行数据处理与搜索&#xff0c;把处理后的数据重新返回到当前页面进行显示加载。可能出现的问题&#xff0c;当再次加载显示页面的时候&#xff0c;出现重复加载form.js的问题&#xff0c;收缩功能无法实现。 2.…

java多线程之Condition的使用

目录 一、Condition的概念 二、Condition的实现分析 &#xff08;1&#xff09;等待 &#xff08;2&#xff09;通知 三、Condition应用 &#xff08;1&#xff09;简单demo &#xff08;2&#xff09;可阻塞队列的应用案例 &#xff08;3&#xff09;多线程轮流执行 一、…

jdk1.8为什么要废除JVM中的永久代(Perm Gen)

作者&#xff1a;liuxiaopeng博客地址&#xff1a;http://www.cnblogs.com/paddix/一、JVM 内存模型根据 JVM 规范&#xff0c;JVM 内存共分为虚拟机栈、堆、方法区、程序计数器、本地方法栈五个部分。1、虚拟机栈&#xff1a;每个线程有一个私有的栈&#xff0c;随着线程的创建…

陈天奇团队新研究:自动优化深度学习工作负载

深度学习在我们的日常生活中已经无处不在。深度学习模型现在可以识别图像&#xff0c;理解自然语言&#xff0c;玩游戏&#xff0c;以及自动化系统决策&#xff08;例如设备放置和索引&#xff09;。张量算符&#xff08;tensor operators&#xff09;&#xff0c;如矩阵乘法和…

java-Semaphore信号量的使用

一、Semaphore概念 Semaphore也叫信号量&#xff0c;在JDK1.5被引入&#xff0c;可以用来控制同时访问特定资源的线程数量&#xff0c;通过协调各个线程&#xff0c;以保证合理的使用资源。Semaphore内部主要通过AQS&#xff08;AbstractQueuedSynchronizer&#xff09;实现线…

Bootstrap 小结

Bootstrap 小结 Bootstrap4特点&#xff1a;1.兼容IE10 2.使用flexbox 布局 3.抛弃Nomalize.css 4.提供布局和 reboot 版本 Bootstrap组成&#xff1a;1.基础样式 2.常用组件 3.JS插件 常见问题&#xff1a; 1.Bootstrap 的优缺点 优点&#xff1a;CSS 代码结构合理 &#xff…