本文主要是介绍Future 和 Callable 学习小计,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
Future 和 Callable 学习小计
- Callable 接口
- Future 接口
- Callable 和 Future 的关系
- get() 方法使用
- 基础使用
- 批量使用
- get(long,TimeUnit) 使用
- 总结
- FutureTask 和 Future
在java 中使用Thread 或 Runnable创建线程的时候是无法获取线程的返回结果和抛出异常信息的,但 java 中提供了Future 和 Callable 两个接口的可以实现获取子线程的执行结果。
Callable 接口
- 类似Runnable,可以被线程池执行的任务
- 实现call方法
- 有返回值
Future 接口
- get() 任务正常完成,该方法会立即返回结果,任务执行完成之前会一直被阻塞
- get(long,TimeUnit) 该方法传入一个延迟的时间和时间单位,如果延迟的时间到了还没有获取到返回结果,则会抛出TimeoutException 异常,在超时异常中任务需要取消
- cancel 取消任务执行方法
- isDone 返回线程是否执行完毕 ture 完成,返回ture 不代表任务可能是成功的完成,可能任务在执行中发生异常或者被取消
- isCancelled 判断任务是否被取消
Callable 和 Future 的关系
- 可以使用Future.get() 方法 获取 Callable 接口执行的返回结果以及限时获取任务的执行结果
- 可以通过Future.isDone() 来判断任务是否已经执行完成了,以及取消这个任务
- 在 Callable 接口中 call() 方法执行完毕之前,主线程调用Future.get() 会被阻塞,直到call() 方法执行完毕后才会获取结果,然后主线程才会切换到runnable 运行状态
get() 方法使用
基础使用
public class FutureDemo {static SimpleDateFormat datetimeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");/*** Future 和 Callable 基础使用方法*/public static void main(String[] args) throws ExecutionException, InterruptedException {ExecutorService executorService = Executors.newFixedThreadPool(1);// 创建Task 对象, 将实例对象放入到线程池中执行, 并得到 Future 对象Task task = new Task();System.out.println("执行开始时间: " + datetimeFormat.format(new Date()));Future<String> future = executorService.submit(task);// future.get() 获取返回值System.out.println(future.get());System.out.println("返回值值时间: " + datetimeFormat.format(new Date()));executorService.shutdown();}/*** 实现 Callable 接口, 重写 call 方法*/static class Task implements Callable<String> {@Overridepublic String call() throws Exception {Thread.sleep(3000);return "call() return success";}}
}
返回结果
批量使用
public class FutureDemoArr {static SimpleDateFormat datetimeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");/*** Future 和 Callable 批量提交任务和接收返回值*/public static void main(String[] args) throws ExecutionException, InterruptedException {ExecutorService executorService = Executors.newFixedThreadPool(2);ArrayList<Future<String>> list = new ArrayList<>();System.out.println("开始时间 : " + datetimeFormat.format(new Date()));// 提交接收返回值for (int i = 0; i < 10; i++) {list.add(executorService.submit(new Task()));}for (Future<String> future : list) {System.out.println(future.get() + " , 得到返回值的时间 : " + datetimeFormat.format(new Date()));}executorService.shutdown();}/*** 实现 Callable 接口, 重写 call 方法*/static class Task implements Callable<String> {@Overridepublic String call() throws Exception {Thread.sleep(2000);return Thread.currentThread().getName() + " : " + RandomUtils.nextInt();}}
}
get(long,TimeUnit) 使用
public class FutureDemoExc {public static void main(String[] args) {// 顾客等待时间int timeout1 = 3000;// 技师返回时间int timeout2 = 5000;Task task = new Task(timeout1, timeout2);Integer num = task.cllNumber();System.out.println("得到的技师: " + num);}/*** Future 和 Callable 发生异常demo, 模仿足疗店点钟场景* 小明 午休时间找个家足疗店想做个足疗,* 小明到了店里告诉商家只等 88 号 3秒, 如果 3 秒不来来个默认的即可*/static class Task implements Callable<Integer> {/*** 顾客等待超时时间*/private Integer timeout1;/*** 88 号技师返回时间*/private Integer timeout2;/*** 默认技师为 1*/private Integer defaultNum = 1;public Task(int timeout1, int timeout2) {this.timeout1 = timeout1;this.timeout2 = timeout2;}public Integer cllNumber() {ExecutorService service = Executors.newFixedThreadPool(1);Future<Integer> future = service.submit(this);try {// 等待返回结果, timeout1 如果超时则抛出 TimeoutException 异常return future.get(timeout1, TimeUnit.MILLISECONDS);} catch (InterruptedException e) {e.printStackTrace();return -1;} catch (ExecutionException e) {e.printStackTrace();return -2;} catch (TimeoutException e) {System.out.println("顾客等待超时 返回默认 ");// 调用 cancel 告诉线程中断future.cancel(true);System.out.println(future.isDone());return defaultNum;} finally {service.shutdown();}}@Overridepublic Integer call() throws Exception {try {Thread.sleep(timeout2);} catch (InterruptedException e) {System.out.println("收到线程中断标识, 返回等不及了返回一个默认的");return 1;}System.out.println(" 88 忙完了 ");return 88;}}
}
返回结果
总结
将 Callable 实例交给线程池,提交时候线程池会返回一个Future ,这个时候 Future 对象就是一个空的容器,当线程的任务执行结束以后,线程池会立即把结果填入到之前给的Future对象中,这样就可以在Future中得到结果了
FutureTask 和 Future
FutureTask 是用来获取Future和任务的结果的, FuturTask 实际上是Future 的包装器, 可以把Callable 转换成 Future 或 Runnable ,它同时实现了二者的接口。
将 FutureTask 传给 Thread 使用
* FutureTask 基础使用*/public static void main(String[] args) throws ExecutionException, InterruptedException {FutureTask<String> futureTask = new FutureTask<>(new Callable<String>() {@Overridepublic String call() throws Exception {Thread.sleep(3000);return "futureTask return success";}});new Thread(futureTask).start();System.out.println(futureTask.get());}
这篇关于Future 和 Callable 学习小计的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!