FutureTask与Fork/Join
在学习多线程的过程中,我们形成了一种思维习惯。那就是对于某个耗时操作不再做同步操作,让他分裂成一个线程之后执行下一步,而线程执行耗时操作。并且我们希望在我们需要它返回的时候再去调用它的结果集。好比我们把米饭和水放进了电饭煲,转头就去炒菜了,等到菜完成之后,转头去查看饭是否完成。多线程造成了并行计算的现象,有时候它们是真的多核计算而有时候只是单核的切换。
FutureTask表示的是一种,异步操作的典范。我提交了任务,在未来我要拿到结果。
考虑一种简单的场景,A问B一个问题,B一时回答不了,B要去考虑一段时间,等到有结果了,再告诉A。
这时,我们需要类A,类B。
package Future; //调用端
public class CallA implements CallBack{
private CallB b;
public CallA(CallB b){
this.b = b;
} public void submitProblem(String problem){
System.out.println("a 提交问题:"+problem);
new Thread(){
public void run(){
b.execute(CallA.this, problem);
}
}.start();
System.out.println("a 提交问题完毕");
} @Override
public void result(String result) {
System.out.println(result);
} }
package Future; //执行处理
public class CallB {
public void execute(CallBack callBack,String problem){
System.out.println("接受问题:"+problem);
System.out.println("开始处理");
try{
Thread.sleep(2000);
}catch (Exception e) {
e.printStackTrace();
}
callBack.result("问题处理结果:abcdefg...");
}
}
类的结构是,A中保留它作用对象B的一个引用,在触发询问问题的时候,A向B提交了一个方法调用,并且同时开启了一个线程,这是它不阻塞的原因。
为“提问题”做一个面向对象的接口。
//回调接口
public interface CallBack {
public void result(String result);
}
他们执行的主流程,十分简单。
public class Main {
public static void main(String[] args) {
CallB b = new CallB();
CallA a = new CallA(b);
a.submitProblem("英文字母");
}
}
熟悉了这个过程,JDK提供了FutureTask的接口。
package Future;
import java.util.concurrent.Callable;
public class RealData implements Callable<String>{
private String data;
public RealData(String data){
this.data = data;
}
@Override
public String call() throws Exception {
StringBuffer sb = new StringBuffer();
for(int i=0;i<10;i++){
sb.append(data);
try{
Thread.sleep(1500);
}catch (Exception e) {
e.printStackTrace();
}
}
return sb.toString();
}
}
实现这个Callable接口,重写call方法,在未来调用get的时候将返回运算结果。
package Future; import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask; //jdk future框架
public class FutureMain {
public static void main(String[] args) throws InterruptedException, ExecutionException {
FutureTask<String> future = new FutureTask<String>(new RealData("a"));
ExecutorService executor = Executors.newFixedThreadPool(1);
executor.submit(future);
System.out.println("请求完毕");
try{
Thread.sleep(1000);
}catch (Exception e) {
}
System.out.println("future task 返回:"+future.get());
}
}
多线程的优势体现在并行计算中,虽然某大佬说研究并行计算是在浪费时间,但是作为一种由多线程产生的技术来说,先了解一下特点。
JDK为我们提供了一套Join/Fork框架,考虑下面这个例子。
package ForkAndJoin;
import java.util.concurrent.RecursiveAction;
public class PrintTask extends RecursiveAction{
private final int Max = 50;
private int start;
private int end;
public PrintTask(int start,int end){
this.start = start;
this.end = end;
}
@Override
protected void compute() {
if((end - start)<Max){
for(int i=start;i<end;i++){
System.out.println("当前线程:"+Thread.currentThread().getName()+" i :"+i);
}
}else{
int middle = (start+end)/2;
PrintTask left = new PrintTask(start, middle);
PrintTask right = new PrintTask(middle, end);
left.fork();
right.fork();
}
}
}
package ForkAndJoin; import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.TimeUnit; public class ForkJoinPoolTest {
public static void main(String[] args) throws InterruptedException {
ForkJoinPool forkJoin = new ForkJoinPool();
forkJoin.submit(new PrintTask(0,200));
forkJoin.awaitTermination(2, TimeUnit.SECONDS);
forkJoin.shutdown();
}
}
在compute方法中写主要的任务处理,这是一个并行计算的小例子。
J/F的模式很像map-reduce模式,将任务分小,然后各个处理。
FutureTask与Fork/Join的更多相关文章
- 一文带你了解J.U.C的FutureTask、Fork/Join框架和BlockingQueue
摘要: J.U.C是Java并发编程中非常重要的工具包,今天,我们就来着重讲讲J.U.C里面的FutureTask.Fork/Join框架和BlockingQueue. 本文分享自华为云社区<[ ...
- FutureTask、Fork/Join、 BlockingQueue
我们之前学习创建线程有Thread和Runnable两种方式,但是两种方式都无法获得执行的结果. 而Callable和Future在任务完成后得到结果. Future是一个接口,表示一个任务的周期 ...
- 九 fork/join CompletableFuture
1: Fork/join fork/join: fork是分叉的意思, join是合并的意思. Fork/Join框架:是JAVA7提供的一个用于并行执行任务的框架,是一个把大任务分割成若干个小任务 ...
- JAVA中的Fork/Join框架
看了下Java Tutorials中的fork/join章节,整理下. 什么是fork/join框架 fork/join框架是ExecutorService接口的一个实现,可以帮助开发人员充分利用多核 ...
- JAVA并行框架:Fork/Join
一.背景 虽然目前处理器核心数已经发展到很大数目,但是按任务并发处理并不能完全充分的利用处理器资源,因为一般的应用程序没有那么多的并发处理任务.基于这种现状,考虑把一个任务拆分成多个单元,每个单元分别 ...
- 聊聊并发(八)——Fork/Join框架介绍
作者 方腾飞 发布于 2013年12月23日 | 被首富的“一个亿”刷屏?不如定个小目标,先把握住QCon上海的优惠吧!2 讨论 分享到:微博微信FacebookTwitter有道云笔记邮件分享 ...
- fork/join使用示例
fork/join框架是用多线程的方式实现分治法来解决问题.fork指的是将问题不断地缩小规模,join是指根据子问题的计算结果,得出更高层次的结果. fork/join框架的使用有一定的约束条件: ...
- Java Concurrency - Fork/Join Framework
Normally, when you implement a simple, concurrent Java application, you implement some Runnable obje ...
- Java 7 Fork/Join 并行计算框架概览
应用程序并行计算遇到的问题 当硬件处理能力不能按摩尔定律垂直发展的时候,选择了水平发展.多核处理器已广泛应用,未来处理器的核心数将进一步发布,甚至达到上百上千的数量.而现在 很多的应用程序在运行在多核 ...
随机推荐
- 为什么数组没有实现Iterable接口,但可以使用foreach语句遍历
在Java中,对于数组为什么能够使用foreach语句一直感觉很困惑. 对于能够使用foreach语句进行遍历的对象,只有两种情况,其中一种是遍历对象必须实现Iterable接口,实现ierator( ...
- memcached的常用命令
memcached 常用命令及使用说明 1.启动Memcache 常用参数 -p <num> 设置TCP端口号(默认设置为: 11211) -U <num> UDP监听端口 ...
- mybatis总结回顾
1.mybatis的介绍 轻量级数据持久层框架,替代hibernate 2.mybatis的入门 导包-->配置文件(类名.xml.SqlMapConfig.xml) 类名.xml:放映射.sq ...
- 二叉树中和为某一值的路径 (java)
问题描述 输入一颗二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径.路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径. 题解 import java.util.Arra ...
- 友盟统计小白教程:创建应用,申请appkey
上回书讲到,我们已经和一个靠谱的人选择一个靠谱的统计平台注册了一个帐号,下面就该创建一个应用了. 介绍一个基础知识: appkey:友盟识别app的唯一标识,目前友盟平台上超过500000款App,每 ...
- centos中如何查看tomcat的版本
centos中如何查看tomcat的版本 如果使用的rpm安装的tomcat,则使用如下命令查看 rpm -q tomcat 如果不是使用rpm安装的tomcat ./catalina.sh vers ...
- Linux执行YUM命令报错解决方案
Loaded plugins: rhnplugin, security This system is not registered with RHN. RHN support will be disa ...
- AppleScript: Handler
AppleScript绝对是个奇葩的存在!不管功能有多强大. Handler有两种,一种是和OC类似的使用Label参数,一种是和javascript类似的使用括号把一堆参数都放在里面的. label ...
- openfire搭建spackweb在线即时聊天
1.首先去openFire官网下载openFire以及spackweb,以下地址可以2样东西一次打包下载.http://download.csdn.net/detail/a315157973/8048 ...
- ERROR 3009 (HY000): Column count of mysql.user is wrong. Expected 45, found 43. Created with MySQL 5
ERROR 3009 (HY000): Column count of mysql.user is wrong. Expected 45, found 43. Created with MySQL 5 ...