异步运算考虑使用Callable接口 有返回值的线程
2015-11-17 17:29
134 查看
多线程应用有两种实现方式,一种是实现Runnable接口,另一种是继承Thread类,这 两个方式都有缺点:run方法没有返回值,不能抛出异常(这两个缺点归根到底是Runable 接口的缺陷,Thread也是实现了 Runnable接口),如果需要知道一个线程的运行结果就需要用 户自行设计,线程类自身也不能提供返回值和异常。但是从Java 1.5开始引入了一个新的接口 Callable,它类似于Runable接口,实现它就可以实现多线程任务,Callable的接口定义如下:
public interface Callable<V> {
//具有返回值,并可抛出异常
V call() throws Exception;
}
实现Callable接口的类,只是表明它是一个可调用的任务,并不表示它具有多线程运算能力,还是需要执行器来执行的。我们先编写一个任务类,代码如下:
这里模拟了一个复杂运算:税款计算器,该运算可能要花费10秒钟的时间,此时不能 让用户一直等着吧,需要给用户输出点什么,让用户知道系统还在运行,这也是系统友好性的体现:用户输入即有输出,若耗时较长,则显示运算进度。如果我们直接计算,就只有一 个main线程,是不可能有友好提示的,如果税金不计算完毕,也不会执行后续动作,所以
此时最好的办法就是重启一个线程来运算,让main线程做进度提示,代码如下:
在该段代码中,Executors是一个静态工具类,提供了异步执行器的创建能力,如单线程 执行器newSingleThreadExecutor、固定线程数量的执行器newFixedThreadPool等,一般它 是异步计算的入口类。Future关注的是线程执行后的结果,比如有没有运行完毕,执行结果 是多少等。此段代码的运行结果如下所示:
##################################################
计算完成,税金是:10元
执行时,“#”会依次递增,表示系统正在运算,为用户提供了运算进度。此类异步计算的好处是:
□尽可能多地占用系统资源,提供快速运算。
□可以监控线程执行的情况,比如是否执行完毕、是否有返回值、是否有异常等。
□可以为用户提供更好的支持,比如例子中的运算进度等。
public interface Callable<V> {
//具有返回值,并可抛出异常
V call() throws Exception;
}
实现Callable接口的类,只是表明它是一个可调用的任务,并不表示它具有多线程运算能力,还是需要执行器来执行的。我们先编写一个任务类,代码如下:
//税款计算器 class TaxCalculator implements Callable<Integer>{ //本金 private int seedMoney; //接收主线程提供的参数 public TaxCalculator(int _seedMoney) { // TODO Auto-generated constructor stub seedMoney=_seedMoney; } @Override public Integer call() throws Exception { // TODO Auto-generated method stub //复杂计算,运行一次需要10秒 TimeUnit.MILLISECONDS.sleep(10000); return seedMoney/10; } }
这里模拟了一个复杂运算:税款计算器,该运算可能要花费10秒钟的时间,此时不能 让用户一直等着吧,需要给用户输出点什么,让用户知道系统还在运行,这也是系统友好性的体现:用户输入即有输出,若耗时较长,则显示运算进度。如果我们直接计算,就只有一 个main线程,是不可能有友好提示的,如果税金不计算完毕,也不会执行后续动作,所以
此时最好的办法就是重启一个线程来运算,让main线程做进度提示,代码如下:
public class TestCallable { public static void main(String[] args) throws Exception { //生成一个单线程的异步执行器 ExecutorService es=Executors.newSingleThreadExecutor(); //线程执行后的期望值 Future<Integer> future=es.submit(new TaxCalculator(100)); while(!future.isDone()){ //还没有运算完成,等待200毫秒 TimeUnit.MICROSECONDS.sleep(200); //输出进度符号 System.out.println("#"); } System.out.println("\n计算完成,税金是:"+future.get()+"元"); es.shutdown(); } }
在该段代码中,Executors是一个静态工具类,提供了异步执行器的创建能力,如单线程 执行器newSingleThreadExecutor、固定线程数量的执行器newFixedThreadPool等,一般它 是异步计算的入口类。Future关注的是线程执行后的结果,比如有没有运行完毕,执行结果 是多少等。此段代码的运行结果如下所示:
##################################################
计算完成,税金是:10元
执行时,“#”会依次递增,表示系统正在运算,为用户提供了运算进度。此类异步计算的好处是:
□尽可能多地占用系统资源,提供快速运算。
□可以监控线程执行的情况,比如是否执行完毕、是否有返回值、是否有异常等。
□可以为用户提供更好的支持,比如例子中的运算进度等。
相关文章推荐
- 短信发送状态报告(Status Report)的处理
- poj 1422 Air Raid(最小路径覆盖)
- 如何去掉datatable的重复行
- poj 3984 迷宫问题【BFS && DFS】【简单】
- AR--小Demo--伴旅
- js 实现倒计时
- coreGraphics绘图
- iOS_ 摸推背景透明效果
- uniGUI试用笔记(十五)通过URL控制参数
- POJ 1144 Network (Tarjan求割点)
- 杭电2734 Quicksum
- Spark入门之九:机器学习简介
- 小菜鸟的第一个实训小项目总结
- LeetCode:Factorial Trailing Zeroes
- weblogic linux启动报错java.net.UnknownHostException
- CSS3 动画 Animation
- jquery 插件 validate 学习
- OC内存管理详解
- 查看apt-get install文件安装到哪里
- 什么是多线程 和GCD 的认识