Callable接口:java
Callable,新启线程的一种方式,返回结果而且可能抛出异常的任务,在前面的新启线程的文章中用过,可是没有具体讲解数据库
优势:编程
能够获取线程的执行结果,也称为返回值服务器
经过与Future的结合,能够实现利用Future来跟踪异步计算的结果网络
Runnable和Callable的区别:并发
Callable规定的方法是call(),Runnable规定的接口是run();dom
Callable的任务执行后可返回值,而Runnable的任务是不能有返回值的;异步
call方法能够抛出异常,run方法不能够ide
运行Callable任务能够拿到一个Future对象,表示异步计算的结果,它提供了检查是否计算完成的方法,以等待计算的完成,并检索计算的结果,经过Future对象能够了解任务执行状况,能够取消任务的执行,还能够获取执行结果spa
Future接口:
Future是一个接口,表明了一个异步计算的结果,接口中的方法用来检查计算是否完成,等待完成和获得计算结果;
当计算完成后,只能经过get()方法获得结果,get()方法会阻塞,一直到线程的计算结果完成并返回;
若是想取消,那么调用cancel()方法,其余方法用于肯定任务是正常完成仍是取消了;
一旦计算完成了,那么这个计算就不能被取消
FutureTask类:
FutureTask类实现了RunnableFuture接口,而RunnableFuture接口是继承了Runnable和Future接口,因此说FutureTask是一个提供异步计算结果的任务;
FutureTask能够用来包装Callable或者Runnable接口的实现对象,由于FutureTask实现了Runnable接口,因此FutureTask也能够提交给线程池
Callable,Future,FutureTask三者之间的关系:
Callable的两种执行方式:
1:借助FutureTask,包装Callable接口的实现类,而后传递给Thread线程执行
package org.dance.day2.future; import org.dance.tools.SleepTools; import java.util.Random; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; /** * Callable的两种执行方式 * @author ZYGisComputer */ public class UseCallable { /** * 实现Callable接口的线程 */ private static class UseCall implements Callable<Integer>{ private int sum; @Override public Integer call() throws Exception { System.out.println("callable子线程开始执行任务计算"); Thread.sleep(2000); for (int i = 0; i < 5000; i++) { sum += i; } System.out.println("子线程任务计算完成,返回值:"+sum); return sum; } } public static void main(String[] args) throws ExecutionException, InterruptedException { UseCall useCall = new UseCall(); // 使用FutureTask包装 FutureTask<Integer> futureTask = new FutureTask<>(useCall); // 包装为Thread Thread thread = new Thread(futureTask); thread.start(); // 开始主线程的任务 Random random = new Random(); SleepTools.second(1); if(random.nextBoolean()){ System.out.println("获取Callable result:"+futureTask.get()); }else{ System.out.println("中断计算"); // 中断计算,取消线程的执行 futureTask.cancel(true); } } }
2:借助线程池来执行
UseCall useCall = new UseCall(); // 建立一个线程池 ExecutorService executorService = Executors.newCachedThreadPool(); Future<Integer> future = executorService.submit(useCall);
线程池这个只粘贴关键代码,线程池的知识就不在这多说了,以后会具体讲解
返回的Future接口的使用和FutureTask是同样的
这个接口实现的线程,是有返回值的
能够说一下我以前用到的场景
是这样的,我以前用到的通常是用于云上,或者存储服务器下载电子文件,就是自己我一个接口就是须要查询数据库并,进行结果的大量计算和结果转换的,同时还要上云上下载比较大的电子文件,因此我采用Callable配合线程池来完成云上文件的下载;
做者:彼岸舞
时间:2020\10\04
内容关于:并发编程
本文来源于网络,只作技术分享,一律不负任何责任