并发编程-Future模式
2016-05-02 17:57
393 查看
1.Future模式有点类似商品订单。比如在网上进行购物,当看中某一件商品时,就可以提交订单。提交订单完毕在家等候送货上门。卖家根据订单取货、发货,并配送到顾客手中。大部分情况下,卖家处理订单没那么快,可能需要几天时间。而这段时间买家不必再家里等候,可以做其他事情。
将此类推到程序设计中,当某一段程序提交了一个请求,期望得到一个答复。但非常不幸的是,服务程序对这个请求的处理可能非常慢。在传统的单线程环境下,调用函数是同步的,也就是说它必须要等到服务程序返回结果后,才能够进行其他处理。而在Future模式下,调用方式该为异步,而原来等待返回的时间段,在主调用函数中,则可以用于处理其他事物。传统程序的调用流程如下图所示。
图1-1 传统串行程序调用流程
采用Future模式设计程序,调用流程如下。
图1-2 Future模式流程图
表1-3 Future模式的主要参与者
2.Future模式的代码实现
2.1Main函数的实现
main函数主要负责调用Client发起请求,并使用返回的数据:
2.2Client的实现
2.3Data的实现
2.4FutureData的实现
FutureData实现了一个快速返回的RealData的包装。是RealData的虚拟实现,因此它可以快速的被构造返回。当使用FutureData的getResult()方法时,程序会阻塞,等待RealData被注入到程序中,才使用RealData的getResult()方法返回。
3.JDK的内置实现
Future模式比较常用,JDK的并发包中,就已经了一中Future模式的实现。JDK中实现的比较复杂,提供了更为丰富的多线程控制功能。核心结构如图:
图3-1 JDK内置的Future模式
可以使用JDK内置的Future模式实现我们的功能,首先实现Callable接口,实现具体的业务逻辑。
在这改进中,RealData的构造变得非常快,其业务逻辑被移到call()方法内,并通过call()方法返回。
main方法修改如下:
将此类推到程序设计中,当某一段程序提交了一个请求,期望得到一个答复。但非常不幸的是,服务程序对这个请求的处理可能非常慢。在传统的单线程环境下,调用函数是同步的,也就是说它必须要等到服务程序返回结果后,才能够进行其他处理。而在Future模式下,调用方式该为异步,而原来等待返回的时间段,在主调用函数中,则可以用于处理其他事物。传统程序的调用流程如下图所示。
图1-1 传统串行程序调用流程
采用Future模式设计程序,调用流程如下。
图1-2 Future模式流程图
表1-3 Future模式的主要参与者
参与者 | 作用 |
Main | 系统启动,调用Client发出请求你 |
Client | 返回Data对象,立即返回FutureData,并开启ClientThread线程装配RealData |
Data | 返回数据的接口 |
Future | Future数据,构造很快,但是是一个虚拟的数据,需要装配RealData |
RealData | 真实数据,其构造是比较慢的 |
2.1Main函数的实现
main函数主要负责调用Client发起请求,并使用返回的数据:
public static void main(String[] args) { // TODO Auto-generated method stub Client client = new Client(); Data data = client.request("test"); System.out.println("----------------------------------"); try { Thread.sleep(2000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("----------------------------------"); System.out.println(data.getResult()); }
2.2Client的实现
public class Client { public Data request(final String req_name) { FutureData fd = new FutureData(); new Thread() { @Override public void run() { // TODO Auto-generated method stub RealData rd = new RealData(req_name); fd.setRd(rd); }; }.start(); return fd; } }
2.3Data的实现
public interface Data { public String getResult(); }
2.4FutureData的实现
FutureData实现了一个快速返回的RealData的包装。是RealData的虚拟实现,因此它可以快速的被构造返回。当使用FutureData的getResult()方法时,程序会阻塞,等待RealData被注入到程序中,才使用RealData的getResult()方法返回。
/** * packed the readdata * @author cosco * */ public class FutureData implements Data { protected RealData rd = null; protected volatile boolean isReady = false; public RealData getRd() { return rd; } public synchronized void setRd(RealData rd) { if(isReady){ return; } this.rd = rd; isReady = true; notifyAll(); } @Override public synchronized String getResult() { // TODO Auto-generated method stub while(!isReady){ try { wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return rd.getResult(); } }
2.5RealData的实现 RealData是最终需要使用的数据模型,它的构造很慢。在这里,使用sleep()函数模拟这个过程:
package org.cosco.thread; /** * * @author cosco * */ public class RealData implements Data { private final String result; public RealData(String param){ StringBuffer sb = new StringBuffer(); for(int i = 0; i < 10; i++){ sb.append(param); try { Thread.sleep(100); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } result = sb.toString(); } @Override public String getResult() { // TODO Auto-generated method stub return result; } }
3.JDK的内置实现
Future模式比较常用,JDK的并发包中,就已经了一中Future模式的实现。JDK中实现的比较复杂,提供了更为丰富的多线程控制功能。核心结构如图:
图3-1 JDK内置的Future模式
可以使用JDK内置的Future模式实现我们的功能,首先实现Callable接口,实现具体的业务逻辑。
import java.util.concurrent.Callable; public class RealData implements Callable<String>{ private String param; public RealData(String param){ this.param = param; } @Override public String call() throws Exception { // TODO Auto-generated method stub StringBuffer sb = new StringBuffer(); for(int i = 0; i < 10; i++){ sb.append(param); Thread.sleep(100); } return sb.toString(); } }
在这改进中,RealData的构造变得非常快,其业务逻辑被移到call()方法内,并通过call()方法返回。
main方法修改如下:
package testthread02; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.FutureTask; public class testmain { public static void main(String[] args) throws InterruptedException, ExecutionException { FutureTask<String> future = new FutureTask<String>(new RealData("a")); ExecutorService es = Executors.newFixedThreadPool(1); es.submit(future); try { Thread.sleep(2000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(future.get()); es.shutdown(); } }
相关文章推荐
- Go 语言 Channel 实现原理精要
- Erlang并发编程介绍
- Java并发编程之性能、扩展性和响应
- java多线程和并发包入门示例
- Java并发编程之阻塞队列详解
- Java并发编程示例(二):获取和设置线程信息
- Java并发编程示例(十):线程组
- Java并发编程示例(八):处理线程的非受检异常
- Java并发编程示例(六):等待线程执行终止
- Java并发编程示例(五):线程休眠与恢复
- Java并发编程之创建线程
- Java并发编程示例(九):本地线程变量的使用
- Java并发编程之栅栏(CyclicBarrier)实例介绍
- 实例讲解Java并发编程之ThreadLocal类
- Java并发编程示例(七):守护线程的创建和运行
- 实例讲解Java并发编程之闭锁
- Java并发编程中构建自定义同步工具
- Java并发编程之显示锁ReentrantLock和ReadWriteLock读写锁
- Java并发编程示例(三):线程中断
- Java并发编程示例(四):可控的线程中断