Callable的Future模式
一、线程实现方式
1.继承Thread类
2.实现Runnable接口
3.线程池
4.Callable
二、无论使用继承Thread类还是实现Runnable接口,还是使用线程池都没有办法解决2个问题
1.线程执行没有返回值结果
2.线程执行没有办法抛出异常,只能自己通过try-catch解决
三、Callable
在java中,创建线程一般有两种方式,一种是继承Thread类,一种是实现Runnable接口。然而,这两种方式的缺点是在线程任务执行结束后,无法获取执行结果。我们一般只能采用共享变量或共享存储以及线程通信的方式实现获得任务结果的目的;
不过,在java中,也提供了使用Callable和Future来实现获取任务结果的操作。Callable用来执行任务,产生结果,而Future用来获得结果;
@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;
}
四、Callable和Runnable的区别
1、Callable能接受一个泛型,然后在call方法中返回一个这个类型的值,而Runnable的run方法没有返回值;
2、Callable的call方法可以抛出异常,而Runnable的run方法不会抛出异常;
五、Future
Future莫斯的核心在于:去除了函数的等待时间,并使得原来需要等待的时间段可以用于处理其他业务逻辑;
Future模式:对于多线程,如果线程A要等待线程B的结果,那么线程A没有必要等待线程B,知道线程B有结果,可以先拿到一个未来的Future,等线程B有结果时再取真实的结果;
1、调用Callable的第一种实现方案
package com.zn.callableTest; import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask; public class MyCallable implements Callable<String> {
@Override
public String call() throws Exception {
System.out.println("Callable接口中重写的Call方法,可以有返回值并且抛出异常");
return "callable";
} //调用Callable的第一种实现方案
public static void main(String[] args) throws ExecutionException, InterruptedException {
MyCallable myCallable=new MyCallable();
//利用FutureTask执行Callable并且接受结果
FutureTask<String> stringFutureTask = new FutureTask<>(myCallable);
//利用线程执行Task任务
new Thread(stringFutureTask).start();
//接受结果FutureTask.get会发生阻塞情况
System.out.println(stringFutureTask.get()); System.out.println("MyCallable执行完毕,返回值结果正确接收~");
}
}
控制台效果:
2、调用Callable的第二种实现方案
package com.zn.callableTest; import java.util.concurrent.*; public class MyCallable implements Callable<String> {
@Override
public String call() throws Exception {
System.out.println("Callable接口中重写的Call方法,可以有返回值并且抛出异常");
return "callable";
} //调用Callable的第二种实现方案
public static void main(String[] args) throws ExecutionException, InterruptedException, TimeoutException {
MyCallable myCallable=new MyCallable();
//创建一个线程池
ExecutorService executorService = Executors.newFixedThreadPool(3);
//创建线程执行任务,接受任务结果
Future<String> future = executorService.submit(myCallable);
//接受返回值
System.out.println(future.get(2000,TimeUnit.MILLISECONDS));
System.out.println("方式二,线程池:MyCallable执行完毕,返回值结果正确接收~");
//停止线程池
executorService.shutdown();
}
}
控制台效果:
六、Future常用方法
V get():获取异步执行的结果,如果没有结果可用,此方法会阻塞知道异步计算完成;
V get(Long timeout,TimeUnit unit):获取异步执行结果,如果没哟结果可用,此方法会阻塞,但是会有时间限制,如果阻塞时间超过设定的timeout时间,该方法将抛出异常;
boolean isDone():如果任务执行结束,无论是正常结束或是中途取消还是发生异常,都返回true;
boolean isCanceller():如果任务完成前被取消,则返回true;
boolean cancel(boolean mayInterrupRunning):如果任务还没有开始,执行cancel方法将返回false;如果任务已经启动,执行cancel方法将以中断执行此任务线程的方式来试图停止任务,如果停止成功,返回true;
当任务已经启动,执行cancel(false)方法将不会对正在执行的任务线程产生影响(让线程正常执行到完成),此时返回false;
当任务已经启动,执行cancel方法将返回false,MayInterruptRunning参数表示是否中断执行中的线程;
实际上Future提供了三种功能:
- 能够中断执行中的任务;
- 判断任务是否执行完成;
- 获取任务执行完成后的结果;
七、Future提供三种功能
1.中断任务cancel(true)
package com.zn.callableTest; import java.util.concurrent.*; public class MyCallable implements Callable<String> {
@Override
public String call() throws Exception {
System.out.println("Callable接口中重写的Call方法,可以有返回值并且抛出异常");
return "callable";
} public static void main(String[] args) throws ExecutionException, InterruptedException, TimeoutException {
MyCallable myCallable=new MyCallable();
//创建一个线程池
ExecutorService executorService = Executors.newFixedThreadPool(3);
//创建线程执行任务,接受任务结果
Future<String> future = executorService.submit(myCallable);
//中断任务
boolean cancel = future.cancel(true);
if(cancel){
System.out.println("中断任务成功~");
}else{
//接受返回值
System.out.println(future.get(2000,TimeUnit.MILLISECONDS)); } //停止线程池
executorService.shutdown();
}
}
控制台效果:
2.判断任务是否执行完成isDone()
3.获取任务执行后的结果get()
八、手写Future模式
package com.zn.callableTest; /**
* 手写Future模式
*/
public class MyFuture {
//FLAG相当于数据标识,如果放入数据成功,则返回为true,否则返回为false
private static boolean FLAG=false;
private String data; public synchronized void setData(String data) throws InterruptedException {
Thread.sleep(2000);
//赋值操作
this.data = data;
FLAG=true;
//唤起
notify();
} public synchronized String getData() {
//如果获取数据失败
if(!FLAG){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return data;
} public static void main(String[] args) {
MyFuture future=new MyFuture();
new Thread(()->{
try {
future.setData("张三");
System.out.println(future.getData());
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
}
控制台效果:
Callable的Future模式的更多相关文章
- java:并发编程-Callable与Future模式
自己对线程池的理解: coresize 3 maxsize 5 blockLinkedQuenue 3 当提交的任务在<=3时,创建三个线程干活 大于3时,把任务先加入阻塞式队列,当有空闲的核心 ...
- 并发编程之Callable异步,Future模式
Callable 在Java中,创建线程一般有两种方式,一种是继承Thread类,一种是实现Runnable接口.然而,这两种方式的缺点是在线程任务执行结束后,无法获取执行结果.我们一般只能采用共享变 ...
- Java线程池(Callable+Future模式)
转: Java线程池(Callable+Future模式) Java线程池(Callable+Future模式) Java通过Executors提供四种线程池 1)newCachedThreadPoo ...
- 线程笔记:Future模式
线程技术可以让我们的程序同时做多件事情,线程的工作模式有很多,常见的一种模式就是处理网站的并发,今天我来说说线程另一种很常见的模式,这个模式和前端里的ajax类似:浏览器一个主线程执行javascri ...
- Java线程(七):Callable和Future
转自:http://blog.csdn.net/ghsau/article/details/7451464 本篇说明的是Callable和Future,它俩很有意思的,一个产生结果,一个拿到结果. C ...
- 并发编程 05—— Callable和Future
Java并发编程实践 目录 并发编程 01—— ThreadLocal 并发编程 02—— ConcurrentHashMap 并发编程 03—— 阻塞队列和生产者-消费者模式 并发编程 04—— 闭 ...
- Java并发(8):CountDownLatch、CyclicBarrier、Semaphore、Callable、Future
CountDownLatch.CyclicBarrier.Semaphore.Callable.Future 都位于java.util.concurrent包下,其中CountDownLatch.C ...
- Future模式
Future模式简介 Future模式有点类似于网上购物,在你购买商品,订单生效之后,你可以去做自己的事情,等待商家通过快递给你送货上门.Future模式就是,当某一程序提交请求,期望得到一个答复.但 ...
- 【Java线程】Callable和Future
Future模式 Future接口是Java线程Future模式的实现,可以来进行异步计算. Future模式可以这样来描述: 我有一个任务,提交给了Future,Future替我完成这个任务.期间我 ...
随机推荐
- Nginx笔记总结二:Nginx编译参数
-prefix= 安装路径-with-http_ssl_module ...
- 学习和使用 Styled Layer Descriptor SLD样式文件
1. SLD 文件大致作用,可以浏览下示意图: 点要素的符号化:http://docs.geoserver.org/stable/en/user/styling/sld-cookbook/points ...
- 本地开启https服务
### ##自签名证书 ##配置Apache服务器SSL ##自己作为CA签发证书 ###这里是OpenSSL和HTTPS的介绍 OpenSSL HTTPS 开启HTTPS配置前提是已在Mac上搭建A ...
- AJAX学习小结
12345678910 $.ajax({ "url":"", //访问路径 "data":"", // 需要传输的数据 ...
- uploadifive如何动态传参
直接上代码 关键:$('#file_upload').data('uploadifive').settings.formData = { 'ID': 'ceshi'}; //动态更改formData的 ...
- IdentityServer4.FreeSql 持久化实现
前言 故事是这样开始的: 然后突然又来了句... 扪心自问自从不知道怎么当了 FreeSql 开发群 () 的管理以来, 几乎没有给 FreeSql 做过什么贡献...惭愧惭愧. 借此机会, 似乎可以 ...
- PHP算法练习2:(175. 组合两个表)
练习地址:https://leetcode-cn.com/problems/combine-two-tables/ 表1: Person +-------------+---------+ | 列名 ...
- Java设计模式二
今天谈的是工厂模式,该模式用于封装和对对象的创建,万物皆对象,那么万物又是产品类,如一个水果厂生产三种水果罐头,我们就可以将这三种水果作为产品类,再定义一个接口用来设定对水果罐头的生成方法,在工厂类中 ...
- 2017、2018面试分享(js面试题记录)记得点赞分享哦;让更多的人看到~~
2017面试分享(js面试题记录) 1. 最简单的一道题 '11' * 2 'a8' * 3 var a = 2, b = 3; var c = a+++b; // c = 5 2. 一道this的问 ...
- 伪元素 before 和 after 初探
伪元素 before 和 after 初探 使用了 CodePen 做演示,欢迎点击预览 定义 首先来看 MDN 的定义: ::before 创建一个伪元素,作为已选中元素的第一个子元素,常通过 co ...