zoukankan      html  css  js  c++  java
  • [改善Java代码]异步运算考虑使用Callable接口

    多线程有两种实现方式:

    一种是实现Runnable接口,另一种是继承Thread类,这两种方式都有缺点,run方法没有返回值,不能抛出异常(这两个缺点归根到底是Runable接口的缺陷,Thread也是实现了Runnable接口),如果需要知道一个线程的运行结果就需要用户自行设计,线程类自身也不能提供返回值和异常.

    但是从JDK1.5之后引入了一个新的接口Callable,它类似于Runnable接口,实现它就可以实现多线程任务,Callable接口的定义如下:

    public interface Callable<V> {
    
        V call() throws Exception;
    }

    实现Callable接口的类,只是表明它是一个可以调用的任务,并不代表它具有多线程运算的能力,还是需要执行器来执行的,编写一个任务类:

     1 import java.util.concurrent.Callable;
     2 import java.util.concurrent.ExecutorService;
     3 import java.util.concurrent.Executors;
     4 import java.util.concurrent.Future;
     5 import java.util.concurrent.TimeUnit;
     6 
     7 public class Client {
     8     public static void main(String[] args) throws Exception {
     9         //生成一个单线程的异步执行器
    10         ExecutorService es = Executors.newSingleThreadExecutor();
    11         //线程执行后的期望值
    12         Future<Integer> future = es.submit(new TaxCalculator(100));
    13         while(!future.isDone()){
    14             //还没有运算完成,等待10毫秒
    15             TimeUnit.MILLISECONDS.sleep(200);
    16             //输出进度符号
    17             System.out.print("#");
    18         }
    19         System.out.println("
    计算完成,税金是:"+ future.get() + " 元");    
    20         //关闭异步执行器
    21         es.shutdown();
    22     }
    23 }
    24 
    25 //税款计算器
    26 class TaxCalculator implements Callable<Integer> {
    27     //本金
    28     private int seedMoney;
    29     //接收主线程提供的参数
    30     public TaxCalculator(int _seedMoney) {
    31         seedMoney = _seedMoney;
    32     }
    33     @Override
    34     public Integer call() throws Exception {
    35         //复杂计算,运行一次需要10秒
    36         TimeUnit.MILLISECONDS.sleep(10000);
    37         return seedMoney /10;
    38     }
    39 }

    这里模拟了一个复杂运算,这个运算可能要花费10秒钟的时间,此时不能让用户一直等着,需要给 用户输出点什么,让用户知道系统还在运行,这也是友好性的体现,用户输入既有输出,若耗时较长,则显示进度.

    如果我们直接计算,就只有一个main线程,是不可能有友好提示的,如果税金不计算完毕,也不会执行后续动作,所以此时最好的方法就是重启一个线程来运算.让main线程做进度提示.

    改段代码中,Executors是一个静态工具类,提供了异步执行器的创建能力,如单线程执行器newSingleThreadExecutor,固定线程数量的执行器newFixedThreadPool等,一般它是异步计算的入口类.

    Future关注的是线程执行后的结果.比如有没有运行完毕,执行结果是多少等.此段代码的运行结果如下:

    ###################################################
    计算完成,税金是:10 元

    "#"会依次递增,标识系统正在计算.

    此类异步运算的好处是:

    1.尽可能多的占用系统资源.提供快速运算.

    2.可以监控线程执行的情况,比如是否执行完毕,是否有返回值,是否有异常.

    3.可以为用户提供更好的支持,比如例子中的运算进度等.

  • 相关阅读:
    代码编写原则
    换个角度看世界
    不使用nib 文件时,需要改变一个view 的大小时,需要为viewcontroller添加loadView方法
    建议:一般地,建议使用xcode 4.3开发app 而不是使用xcode4.5
    iOS 5解决Could not instantiate class named NSLayoutConstraint问题
    访问对象方法比较
    让一个view 或者控件不支持拖拽
    Java Map遍历方式的选择
    Java里多个Map的性能比较(TreeMap、HashMap、ConcurrentSkipListMap)
    java List集合记录 ArrayList和LinkedList的区别
  • 原文地址:https://www.cnblogs.com/DreamDrive/p/5623991.html
Copyright © 2011-2022 走看看