新的起点 新的开始

快乐生活 !

深入浅出多线程(3)-Future异步模式以及在JDK1.5Concurrent包中的实现

   接深入浅出多线程(2)在多线程交互的中,经常有一个线程需要得到另个一线程的计算结果,我们常用的是Future异步模式来加以解决。
   什么是Future模式呢?Future 顾名思义,在金融行业叫期权,市场上有看跌期权和看涨期权,你可以在现在(比如九月份)购买年底(十二月)的石油,假如你买的是看涨期权,那么如果石油真的涨了,你也可以在十二月份依照九月份商定的价格购买。扯远了,Future就是你可以拿到未来的结果。对于多线程,如果线程A要等待线程B的结果,那么线程A没必要等待B,直到B有结果,可以先拿到一个未来的Future,等B有结果是再取真实的结果。其实这个模式用的很多,比如浏览器下载图片的时候,刚开始是不是通过模糊的图片来代替最后的图片,等下载图片的线程下载完图片后在替换。如图所示:


  • 在没有JDK1.5提供的Concurrent之前,我们通过自定义一个结果类,负责结果持有。
如下面代码:
package vincent.blogjava.net;

public class FutureResult {
    
private String result;
    
private boolean isFinish =false;
    
public String getResult() {
        
return result;
    }
    
public synchronized void setResult(String result) {
        
this.result = result;
        
this.isFinish = true;
    }
    
public synchronized boolean isFinish() {
        
return isFinish;
    }

}
存储结果值和是否完成的Flag。
package vincent.blogjava.net;

public class GenerateResultThread extends Thread{
    FutureResult fr ;
    
public GenerateResultThread(FutureResult fr ){
        
this.fr = fr;
    }
    
public  void run(){
        
//模仿大量耗时计算后(5s)返回结果。
        try {
            System.out.println(
"GenerateResultThread开始进行计算了!");
            Thread.sleep(
5000);
        } 
catch (InterruptedException e) {
            
// TODO Auto-generated catch block
            e.printStackTrace();
        }
        fr.setResult(
"ResultByGenerateResultThread");
    }
}
计算具体业务逻辑并放回结果的线程。
package vincent.blogjava.net;

public class Main {

    
/**
     * 
@param args
     * 
@throws InterruptedException 
     
*/
    
public static void main(String[] args) throws InterruptedException {
        
// TODO Auto-generated method stub
       FutureResult fr = new FutureResult();
       
new GenerateResultThread(fr).start();
       
//main线程无需等待,不会被阻塞。
       
//模仿 干自己的活 2s。
       Thread.sleep(2000);
       
// 估计算完了吧 取取试试。
       System.out.println("过来2s了,看看有结果吗?");
       
if(!fr.isFinish()){System.out.println("还没有完成呢! 继续干自己活吧!");}
       
//模仿 干自己的活 4s。
       Thread.sleep(4000);
       System.out.println(
"过来4s了,看看有结果吗?");
       
if(fr.isFinish()){
           System.out.println(
"完成了!");
           System.out.println(
"Result:"+fr.getResult());
           
       }
    }

}
Main方法需要GenerateResultThread线程计算的结果,通过这种模式,main线程不需要阻塞。结果如下:
GenerateResultThread开始进行计算了!
过来2s了,看看有结果吗?
还没有完成呢! 继续干自己活吧!
过来4s了,看看有结果吗?
完成了!
Result:ResultByGenerateResultThread
  •  在JDK1.5 Concurrent 中,提供了这种Callable的机制。我们只要实现Callable接口中的Call方法,Call方法是可以返回任意类型的结果的。如下:
package vincent.blogjava.net;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;

public class ConcurrentImpl {

public static void main(String[] args) throws InterruptedException, Exception {
    FutureTask  fr 
= new FutureTask(new Returnresult());
    
new Thread(fr).start();
       
//main线程无需等待,不会被阻塞。
       
//模仿 干自己的活 2s。
       Thread.sleep(2000);
       
// 估计算完了吧 取取试试。
       System.out.println("过来2s了,看看有结果吗?");
       
if(!fr.isDone()){System.out.println("还没有完成呢! 继续干自己活吧!");}
       
//模仿 干自己的活 4s。
       Thread.sleep(4000);
       System.out.println(
"过来4s了,看看有结果吗?");
       
if(fr.isDone()){
           System.out.println(
"完成了!");
           System.out.println(
"Result:"+fr.get());
}
}
}
class Returnresult implements Callable{

    @Override
    
public Object call() throws Exception {
        
//模仿大量耗时计算后(5s)返回结果。
        System.out.println("GenerateResultThread开始进行计算了!");
        Thread.sleep(
11000);
        
return "ResultByGenerateResultThread";
    }
    
}
Returnresult 实现了Callable接口,在Call方法中实现业务逻辑,并返回结果。在Main方法里面,初始化FutureTask 并将该Task作为Runnable加入Thread后,启动线程。得到跟刚才相同的效果。
注意: 通过JDK标准的Future后,没有必要增加额外的Object来只有Result,更加简单明了,同时FutureTask还提供了Cancel的功能,我们持有FutureTask引用后可以Cancel该线程。通过get()取值是,如果结果还没有返回,将会阻塞Main线程。

  •   其实JDK 实现Future模式的秘密就在FutureTask类里:
FutureTask是实现了Future 和Runnable,对了就是Runnbale接口,我们就可以把它构造到Thread里,启动执行了。
看看,当 new Thread(new FutureTask(new Callable())).start 时:
看图:
G
get 方法取result值,FutureTask 提供Timeout 功能,如果超时,抛出异常。


posted on 2008-09-03 00:57 advincenting 阅读(2531) 评论(4)  编辑  收藏

评论

# re: 深入浅出多线程(3)-Future异步模式以及在JDK1.5Concurrent包中的实现[未登录] 2008-09-03 08:40 tester

好文  回复  更多评论   

# re: 深入浅出多线程(3)-Future异步模式以及在JDK1.5Concurrent包中的实现 2008-09-03 08:53 denni

写的深入浅出,很好  回复  更多评论   

# re: 深入浅出多线程(3)-Future异步模式以及在JDK1.5Concurrent包中的实现 2008-09-03 18:15 Jack.Wang

虽然东西很简单,但写的很认真!很好!  回复  更多评论   

# re: 深入浅出多线程(3)-Future异步模式以及在JDK1.5Concurrent包中的实现 2009-02-12 17:24 wego

不错!我试了一下,很好!  回复  更多评论   


只有注册用户登录后才能发表评论。


网站导航:
 

公告

Locations of visitors to this page

导航

<2008年9月>
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

统计

常用链接

留言簿(13)

随笔分类(71)

随笔档案(179)

文章档案(13)

新闻分类

IT人的英语学习网站

JAVA站点

优秀个人博客链接

官网学习站点

生活工作站点

最新随笔

搜索

积分与排名

最新评论

阅读排行榜

评论排行榜