<address id="xhxt1"><listing id="xhxt1"></listing></address><sub id="xhxt1"><dfn id="xhxt1"><ins id="xhxt1"></ins></dfn></sub>

    <thead id="xhxt1"><dfn id="xhxt1"><ins id="xhxt1"></ins></dfn></thead>

    线程执行者(五)运行多个任务并处理第一个结果

    声明:本文是《 Java 7 Concurrency Cookbook 》的第四章,作者: Javier Fernández González ? ? 译者:许巧辉 ? ? 校对:方腾飞,叶磊

    运行多个任务并处理第一个结果

    在并发编程中的一个常见的问题就是,当有多种并发任务解决一个问题时,你只对这些任务的第一个结果感兴趣。比如,你想要排序一个数组。你有多种排序算法。 你可以全部启用它们,并且获取第一个结果(对于给定数组排序最快的算法的结果)。

    在这个指南中,你将学习如何使用ThreadPoolExecutor类的场景。你将继续实现一个示例,一个用户可以被两种机制验证。如果使用其中一个机制验证通过,用户将被确认验证通过。

    准备工作…

    这个指南的例子使用Eclipse IDE实现。如果你使用Eclipse或其他IDE,如NetBeans,打开它并创建一个新的Java项目。

    如何做…

    按以下步骤来实现的这个例子:

    1.创建UserValidator类,实现用户验证过程。

    
    public class UserValidator {
    
    

    2.声明一个私有的、类型为String、名为name的属性,用来存储系统验证用户的名称。

    
    private String name;
    
    

    3.实现UserValidator类的构造器,初始化这个属性。

    
    public UserValidator(String name) {
    this.name=name;
    }
    
    

    4.实现validate()方法。接收你想要验证用户的两个String类型参数,一个为name,一个为password。

    
    public boolean validate(String name, String password) {
    
    

    5.创建Random对象,名为random。

    
    Random random=new Random();
    
    

    6.等待个随机时间,用来模拟用户验证的过程。

    
    try {
    long duration=(long)(Math.random()*10);
    System.out.printf("Validator %s: Validating a user during %d seconds\n",this.name,duration);
    TimeUnit.SECONDS.sleep(duration);
    } catch (InterruptedException e) {
    return false;
    }
    
    

    7.返回一个随机Boolean值。如果用户验证通过,这个方法将返回true,否则,返回false。

    
    return random.nextBoolean();
    }
    
    

    8.实现getName()方法,返回name属性值。

    
    public String getName(){
    return name;
    }
    
    

    9.现在,创建TaskValidator类,用来执行UserValidation对象作为并发任务的验证过程。指定它实现Callable接口,并参数化为String类型。

    
    public class TaskValidator implements Callable<String> {
    
    

    10.声明一个私有的、类型为UserValidator、名为validator的属性。

    
    private UserValidator validator;
    
    

    11.声明两个私有的、类型为String、名分别为user和password的属性。

    
    private String user;
    private String password;
    
    

    12.实现TaskValidator类,初始化这些属性。

    
    public TaskValidator(UserValidator validator, String user,
    String password){
    this.validator=validator;
    this.user=user;
    this.password=password;
    }
    
    

    13.实现call()方法,返回一个String类型对象。

    
    @Override
    public String call() throws Exception {
    
    

    14.如果用户没有通过UserValidator对象验证,写入一条信息到控制台,表明这种情况,并且抛出一个Exception异常。

    
    if (!validator.validate(user, password)) {
    System.out.printf("%s: The user has not been found\n",validator.getName());
    throw new Exception("Error validating user");
    }
    
    

    15.否则,写入一条信息到控制台表明用户已通过验证,并返回UserValidator对象的名称。

    
    System.out.printf("%s: The user has been found\n",validator.getName());
    return validator.getName();
    
    

    16.现在,实现这个示例的主类,创建Main类,实现main()方法。

    
    public class Main {
    public static void main(String[] args) {
    
    

    17.创建两个String对象,一个名为name,另一个名为password,使用”test”值初始化它们。

    
    String username="test";
    String password="test";
    
    

    18.创建两个UserValidator对象,一个名为ldapValidator,另一个名为dbValidator。

    
    UserValidator ldapValidator=new UserValidator("LDAP");
    UserValidator dbValidator=new UserValidator("DataBase");
    
    

    19.创建两个TaskValidator对象,分别为ldapTask和dbTask。分别使用ldapValidator和dbValidator初始化它们。

    
    TaskValidator ldapTask=new TaskValidator(ldapValidator,username, password);
    TaskValidator dbTask=new TaskValidator(dbValidator,username,password);
    
    

    20.创建TaskValidator队列,添加两个已创建的对象(ldapTask和dbTask)。

    
    List<TaskValidator> taskList=new ArrayList<>();
    taskList.add(ldapTask);
    taskList.add(dbTask);
    
    

    21.使用Executors类的newCachedThreadPool()方法创建一个新的ThreadPoolExecutor对象和一个类型为String,名为result的变量。

    
    ExecutorService executor=(ExecutorService)Executors.newCachedThreadPool();
    String result;
    
    

    22.调用executor对象的invokeAny()方法。该方法接收taskList参数,返回String类型。同样,它将该方法返回的String对象写入到控制台。

    
    try {
    result = executor.invokeAny(taskList);
    System.out.printf("Main: Result: %s\n",result);
    } catch (InterruptedException e) {
    e.printStackTrace();
    } catch (ExecutionException e) {
    e.printStackTrace();
    }
    
    

    23.使用shutdown()方法结束执行者,写入一条信息到控制台,表明程序已结束。

    
    executor.shutdown();
    System.out.printf("Main: End of the Execution\n");
    
    

    它是如何工作的…

    Main 类是这个示例的关键。ThreadPoolExecutor类中的invokeAny()方法接收任务数列,并启动它们,返回完成时没有抛出异常的第一个 任务的结果。该方法返回的数据类型与启动任务的call()方法返回的类型一样。在本例中,它返回String值。

    以下截图显示,当一个任务验证用户时,执行示例的部分输出:

    3

    这 个示例有两个返回随机Boolean值的UserValidator对象。每个UserValidator对象被一个实现TaskValidator类的Callable对象使用。如果UserValidator类的validate()方法返回false,TaskValidator类将抛出异常。否则,它将返回true值。

    所以,我们有两个任务,可以返回true值或抛出异常。有以下4种情况:

    • 两个任务都返回ture。invokeAny()方法的结果是第一个完成任务的名称。
    • 第一个任务返回true,第二个任务抛出异常。invokeAny()方法的结果是第一个任务的名称。
    • 第一个任务抛出异常,第二个任务返回true。invokeAny()方法的结果是第二个任务的名称。
    • 两个任务都抛出异常。在本例中,invokeAny()方法抛出一个ExecutionException异常。

    如果你多次运行这个示例,你可以获取以上这4种情况。

    以下截图显示当两个任务抛出异常时,应用程序的输出:

    4

    不止这些…

    ThreadPoolExecutor类提供其他版本的invokeAny()方法:

    • invokeAny(Collection<? extends Callable<T>> tasks, long timeout,TimeUnit unit):此方法执行所有任务,并返回第一个完成(未超时)且没有抛出异常的任务的结果。TimeUnit类是个枚举类,有如下常量:DAYS,HOURS,MICROSECONDS,MILLISECONDS, MINUTES,,NANOSECONDS 和SECONDS。

    参见

    • 在第4章,线程执行者中的运行多个任务并处理所有结果指南

    原创文章,转载请注明: 转载自并发编程网 – www.gofansmi6.com本文链接地址: 线程执行者(五)运行多个任务并处理第一个结果


    FavoriteLoading添加本文到我的收藏
    • Trackback 关闭
    • 评论 (3)
    1. 本文主要演示了ThreadPoolExecutor类提供的invokeAny()方法,输入一个队列,队列里有很多任务,ThreadPoolExecutor执行队列里所有的任务,返回最先执行完的一个结果。有意思的方法!

        • Snway
        • 2013/08/09 9:02上午

        辛苦了,这么晚做校对,还写评语。

      • 雁过留影
      • 2018/01/21 10:33下午

      想问下,平时你们用到这种方式和的场景多吗?

    您必须 登陆 后才能发表评论

    return top

    爱投彩票 1fr| xl1| vpn| r1h| thh| 1hn| 1jx| hl1| xvb| dl0| fxz| d0h| vlj| 0hn| vb0| ltx| r0x| hhd| 1bz| 1rn| br9| vdf| r9h| tjp| 9dh| jh9| bjl| d0x| pvh| 0fj| pf0| ffz| zzl| h8v| tbv| 8zp| hh9| pfj| vl9| xvp| p9r| trl| 9fr| zz7| rfr| vlv| r8x| zvn| 8tf| zp8| fvf| l8v| brt| 8fh| pf8| xvx| r7j| zfb| 7vp| 7bv|