Callable

在Java中,创建线程一般有两种方式,一种是继承Thread类,一种是实现Runnable接口。然而,这两种方式的缺点是在线程任务执行结束后,无法获取执行结果。我们一般只能采用共享变量或共享存储区以及线程通信的方式实现获得任务结果的目的。

不过,Java中,也提供了使用Callable和Future来实现获取任务结果的操作。Callable用来执行任务,产生结果,而Future用来获得结果。

Callable接口的定义如下:

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

与Runnable接口不同之处在于,call方法带有泛型返回值V。

Future模式

Future模式的核心在于:去除了主函数的等待时间,并使得原本需要等待的时间段可以用于处理其他业务逻辑

Futrure模式:对于多线程,如果线程A要等待线程B的结果,那么线程A没必要等待B,直到B有结果,可以先拿到一个未来的Future,等B有结果是再取真实的结果。

在多线程中经常举的一个例子就是:网络图片的下载,刚开始是通过模糊的图片来代替最后的图片,等下载图片的线程下载完图片后在替换。而在这个过程中可以做一些其他的事情。

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 wn: 
 * @version 上午16:53:57 
 * 类说明 
 */
public class ThreadCallTest {
  public static void main(String[]args){
ExecutorService executor=Executors.newCachedThreadPool();
Task task=new Task();
Future<Integer> result=executor.submit(task);
if (executor != null)
executor.shutdown();
  
try {
System.out.println("call result"+result.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
System.out.println("over");
  
  }
} class Task implements Callable<Integer>{
@Override
public Integer call() throws Exception {
System.out.println("3.开始 ....");
Thread.sleep(3000);
System.out.println("4.结束 ....");
return "xyz";
}
}

当Task启动后不影响主线程运行,result.get()会等待3秒后返回结果xyz

Future常用方法

V get() :获取异步执行的结果,如果没有结果可用,此方法会阻塞直到异步计算完成。

V get(Long timeout , TimeUnit unit) :获取异步执行结果,如果没有结果可用,此方法会阻塞,但是会有时间限制,如果阻塞时间超过设定的timeout时间,该方法将抛出异常。

boolean isDone() :如果任务执行结束,无论是正常结束或是中途取消还是发生异常,都返回true。 => result.isDone()

boolean isCanceller() :如果任务完成前被取消,则返回true。

boolean cancel(boolean mayInterruptRunning) :如果任务还没开始,执行cancel(...)方法将返回false;如果任务已经启动,执行cancel(true)方法将以中断执行此任务线程的方式来试图停止任务,如果停止成功,返回true;

当任务已经启动,执行cancel(false)方法将不会对正在执行的任务线程产生影响(让线程正常执行到完成),此时返回false;

当任务已经完成,执行cancel(...)方法将返回false。mayInterruptRunning参数表示是否中断执行中的线程。

实际上Future提供了3种功能:

  • (1)能够中断执行中的任务
  • (2)判断任务是否执行完成
  • (3)获取任务执行完成后的结果

个人博客 蜗牛

并发编程之Callable异步,Future模式的更多相关文章

  1. 并发编程 05—— Callable和Future

    Java并发编程实践 目录 并发编程 01—— ThreadLocal 并发编程 02—— ConcurrentHashMap 并发编程 03—— 阻塞队列和生产者-消费者模式 并发编程 04—— 闭 ...

  2. python并发编程之asyncio协程(三)

    协程实现了在单线程下的并发,每个协程共享线程的几乎所有的资源,除了协程自己私有的上下文栈:协程的切换属于程序级别的切换,对于操作系统来说是无感知的,因此切换速度更快.开销更小.效率更高,在有多IO操作 ...

  3. [转载]并发编程之Operation Queue和GCD

    并发编程之Operation Queue http://www.cocoachina.com/applenews/devnews/2013/1210/7506.html 随着移动设备的更新换代,移动设 ...

  4. Java并发编程之CAS

    CAS(Compare and swap)比较和替换是设计并发算法时用到的一种技术.简单来说,比较和替换是使用一个期望值和一个变量的当前值进行比较,如果当前变量的值与我们期望的值相等,就使用一个新值替 ...

  5. python并发编程之gevent协程(四)

    协程的含义就不再提,在py2和py3的早期版本中,python协程的主流实现方法是使用gevent模块.由于协程对于操作系统是无感知的,所以其切换需要程序员自己去完成. 系列文章 python并发编程 ...

  6. python并发编程之multiprocessing进程(二)

    python的multiprocessing模块是用来创建多进程的,下面对multiprocessing总结一下使用记录. 系列文章 python并发编程之threading线程(一) python并 ...

  7. Python进阶:并发编程之Futures

    区分并发和并行 并发(Concurrency). 由于Python 的解释器并不是线程安全的,为了解决由此带来的 race condition 等问题,Python 便引入了全局解释器锁,也就是同一时 ...

  8. Python核心技术与实战——十七|Python并发编程之Futures

    不论是哪一种语言,并发编程都是一项非常重要的技巧.比如我们上一章用的爬虫,就被广泛用在工业的各个领域.我们每天在各个网站.App上获取的新闻信息,很大一部分都是通过并发编程版本的爬虫获得的. 正确并合 ...

  9. 并发编程之J.U.C的第一篇

    并发编程之J.U.C AQS 原理 ReentrantLock 原理 1. 非公平锁实现原理 2)可重入原理 3. 可打断原理 5) 条件变量实现原理 3. 读写锁 3.1 ReentrantRead ...

随机推荐

  1. linux服务器磁盘挂载

    1.先查看当前服务器挂载的磁盘个数 fdisk -l 2.将vdb磁盘挂载到/data目录下 mount /dev/vdb /data 3.df -h  检查磁盘挂载的情况

  2. 团队作业-Beta冲刺(3/4)

    队名:软工9组 组长博客:https://www.cnblogs.com/cmlei/ 作业博客:https://edu.cnblogs.com/campus/fzu/SoftwareEngineer ...

  3. 【深入学习linux】系统分区与格式化

    分区:把大硬盘分为小的逻辑分区 格式化:写入文件系统 分区设备文件名:给每个分区定义设备文件名 挂载:给每个分区分配挂载点 分区->格式化->取名->分配挂载点(WINDOW下的盘弧 ...

  4. 数据分析入门——pandas之DataFrame数据丢失

    一.数据丢失分类 1)nd中分为两种:None和np.nan(NaN) 其中,None是python中的对象,是一个object:而nan是一个float类型 两种不同的类型,运算速度也是不同的 2) ...

  5. k8s记录-kube-dns(core-dns)配置(七)

    docker search corednsdocker pull xxx 拉取镜像(根据实际情况选择)docker tag xxx coredns/coredns:latestdocker tag c ...

  6. Laya改变文档结构后GameConfig自动生成错误问题

    原来的WeaponPanel,ItemPanel,PetPanel改变了路径,然后GameConfig还是一直生成旧的路径,因为旧路径已经不存在,所以提示报错,编译不过去. 需要把编辑模式下的改路径相 ...

  7. 在使用redis做缓存后,mybatis的延迟加载失效

    原来使用的是EHcache,mybatis延迟加载没有问题,改成redis后,延迟加载获得数据时就会发生错误. 报:Cannot get Configuration as configuration ...

  8. Oracle:时间字段模糊查询

    需要查询某一天的数据,但是库里面存的是下图date类型 将Oracle中时间字段转化成字符串,然后进行字符串模糊查询 select * from CAINIAO_MONITOR_MSG t WHERE ...

  9. linux下RAR和ZIP安装和使用

    服务器没装rar,对于上传是压缩的文件来说,是个很大的问题. 源码安装rar: 1. 下载: wget http://www.rarlab.com/rar/rarlinux-x64-4.2.0.tar ...

  10. C++中int型数据的十六进制写法

    C++中int类型数据的十六进制写法 在C++中,int类型一般表示一个有符号的32位整数.在一些情况下(例如进行位操作时)我们需要使用十六进制的方式来表示int类型.int32的取值范围:最大值:2 ...