执行者分离任务的启动和结果的处理

来源:互联网 发布:苹果电脑装机必备软件 编辑:程序博客网 时间:2024/06/09 19:30

执行者分离任务的启动和结果的处理

通常,当你使用执行者执行并发任务时,你将会提交 Runnable或Callable任务给这个执行者,并获取Future对象控制这个方法。你可以发现这种情况,你需要提交任务给执行者在一个对象中,而处理结果在另一个对象中。基于这种情况,Java并发API提供CompletionService类。

CompletionService 类有一个方法来提交任务给执行者和另一个方法来获取已完成执行的下个任务的Future对象。在内部实现中,它使用Executor对象执行任务。这种行为的优点是共享一个CompletionService对象,并提交任务给执行者,这样其他(对象)可以处理结果。其局限性是,第二个对象只能获取那些已经完成它们的执行的任务的Future对象,所以,这些Future对象只能获取任务的结果。

在这个指南中,你将学习如何使用CompletionService类把执行者启动任务和处理它们的结果分开。

代码

package com.packtpub.java7.concurrency.chapter4.recipe11.core;import java.util.concurrent.CompletionService;import java.util.concurrent.ExecutorCompletionService;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.TimeUnit;import com.packtpub.java7.concurrency.chapter4.recipe11.task.ReportProcessor;import com.packtpub.java7.concurrency.chapter4.recipe11.task.ReportRequest;/** * Main class of the example creates all the necessary objects and throws the tasks * */public class Main {    /**     * @param args     */    public static void main(String[] args) {        // Create the executor and thee CompletionService using that executor        ExecutorService executor=(ExecutorService)Executors.newCachedThreadPool();        CompletionService<String> service=new ExecutorCompletionService<>(executor);        // Crete two ReportRequest objects and two Threads to execute them        ReportRequest faceRequest=new ReportRequest("Face", service);        ReportRequest onlineRequest=new ReportRequest("Online", service);        Thread faceThread=new Thread(faceRequest);        Thread onlineThread=new Thread(onlineRequest);        // Create a ReportSender object and a Thread to execute  it        ReportProcessor processor=new ReportProcessor(service);        Thread senderThread=new Thread(processor);        // Start the Threads        System.out.printf("Main: Starting the Threads\n");        faceThread.start();        onlineThread.start();        senderThread.start();        // Wait for the end of the ReportGenerator tasks        try {            System.out.printf("Main: Waiting for the report generators.\n");            faceThread.join();            onlineThread.join();        } catch (InterruptedException e) {            e.printStackTrace();        }        // Shutdown the executor        System.out.printf("Main: Shuting down the executor.\n");        executor.shutdown();        try {            executor.awaitTermination(1, TimeUnit.DAYS);        } catch (InterruptedException e) {            e.printStackTrace();        }        // End the execution of the ReportSender        processor.setEnd(true);        System.out.printf("Main: Ends\n");    }}
package com.packtpub.java7.concurrency.chapter4.recipe11.task;import java.util.concurrent.Callable;import java.util.concurrent.TimeUnit;/** * This class simulates the generation of a report. Is a Callable * object that will be executed by the executor inside a  * CompletionService * */public class ReportGenerator implements Callable<String> {    /**     * The sender of the report     */    private String sender;    /**     * The title of the report     */    private String title;    /**     * Constructor of the class. Initializes the two attributes     * @param sender The sender of the report     * @param title The title of the report     */    public ReportGenerator(String sender, String title){        this.sender=sender;        this.title=title;    }    /**     * Main method of the ReportGenerator. Waits a random period of time     * and then generates the report as a String.     */    @Override    public String call() throws Exception {        try {            Long duration=(long)(Math.random()*10);            System.out.printf("%s_%s: ReportGenerator: Generating a report during %d seconds\n",this.sender,this.title,duration);            TimeUnit.SECONDS.sleep(duration);        } catch (InterruptedException e) {            e.printStackTrace();        }        String ret=sender+": "+title;        return ret;    }}
package com.packtpub.java7.concurrency.chapter4.recipe11.task;import java.util.concurrent.CompletionService;/** * This class represents every actor that can request a report. For this example, * it simply create three ReportGenerator objects and execute them through a  * CompletionService * */public class ReportRequest implements Runnable {    /**     * Name of this ReportRequest     */    private String name;    /**     * CompletionService used for the execution of the ReportGenerator tasks     */    private CompletionService<String> service;    /**     * Constructor of the class. Initializes the parameters     * @param name Name of the ReportRequest     * @param service Service used for the execution of tasks     */    public ReportRequest(String name, CompletionService<String> service){        this.name=name;        this.service=service;    }    /**     * Main method of the class. Create three ReportGenerator tasks and executes them     * through a CompletionService     */    @Override    public void run() {            ReportGenerator reportGenerator=new ReportGenerator(name, "Report");            service.submit(reportGenerator);    }}
package com.packtpub.java7.concurrency.chapter4.recipe11.task;import java.util.concurrent.CompletionService;import java.util.concurrent.ExecutionException;import java.util.concurrent.Future;import java.util.concurrent.TimeUnit;/** * This class will take the results of the ReportGenerator tasks executed through * a CompletinoService * */public class ReportProcessor implements Runnable {    /**     * CompletionService that executes the ReportGenerator tasks     */    private CompletionService<String> service;    /**     * Variable to store the status of the Object. It will executes until the variable     * takes the true value     */    private boolean end;    /**     * Constructor of the class. It initializes the attributes of the class     * @param service The CompletionService used to execute the ReportGenerator tasks     */    public ReportProcessor (CompletionService<String> service){        this.service=service;        end=false;    }    /**     * Main method of the class. While the variable end is false, it     * calls the poll method of the CompletionService and waits 20 seconds     * for the end of a ReportGenerator task     */    @Override    public void run() {        while (!end){            try {                Future<String> result=service.poll(20, TimeUnit.SECONDS);                if (result!=null) {                    String report=result.get();                    System.out.printf("ReportReceiver: Report Recived: %s\n",report);                }                       } catch (InterruptedException e) {                e.printStackTrace();            } catch (ExecutionException e) {                e.printStackTrace();            }        }        System.out.printf("ReportSender: End\n");    }    /**     * Method that establish the value of the end attribute     * @param end New value of the end attribute.     */    public void setEnd(boolean end) {        this.end = end;    }}

结果

Main: Starting the Threads
Main: Waiting for the report generators.
Main: Shuting down the executor.
Online_Report: ReportGenerator: Generating a report during 7 seconds
Face_Report: ReportGenerator: Generating a report during 2 seconds
ReportReceiver: Report Recived: Face: Report
ReportReceiver: Report Recived: Online: Report
ReportSender: End
Main: Ends

工作原理

在示例的主类中,你使用Executors类的newCachedThreadPool()方法创建ThreadPoolExecutor。然后,使用这个对象初始化一个CompletionService对象,因为CompletionService需要使用一个执行者来执行任务。利用CompletionService执行一个任务,你需要使用submit()方法,如在ReportRequest类中。

当其中一个任务被执行,CompletionService完成这个任务的执行时,这个CompletionService在一个队列中存储Future对象来控制它的执行。poll()方法用来查看这个列队,如果有任何任务执行完成,那么返回列队的第一个元素,它是一个已完成任务的Future对象。当poll()方法返回一个Future对象时,它将这个Future对象从队列中删除。这种情况下,你可以传两个属性给那个方法,表明你想要等任务结果的时间,以防队列中的已完成任务的结果是空的。

一旦CompletionService对象被创建,你创建2个ReportRequest对象,用来执行3个ReportGenerator任务,每个都在CompletionService中,和一个ReportSender任务,它将会处理已提交给2个ReportRequest对象的任务所产生的结果。

扩展

CompletionService类可以执行Callable和Runnable任务。在这个示例中,你已经使用Callable,但你同样可以提交Runnable对象。由于Runnable对象不会产生结果,CompletionService类的理念不适用于这些情况。

这个类同样提供其他两个方法,用来获取已完成任务的Future对象。这两个方法如下:


poll():不带参数版本的poll()方法,检查是否有任何Future对象在队列中。如果列队是空的,它立即返回null。否则,它返回第一个元素,并从列队中删除它。


take():这个方法,不带参数。检查是否有任何Future对象在队列中。如果队列是空的,它阻塞线程直到队列有一个元素。当队列有元素,它返回第一元素,并从列队中删除它。

转载请注明: 转载自并发编程网 – ifeve.com本文链接地址: 线程执行者(十一)执行者分离任务的启动和结果的处理

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 电脑显示器闪屏然后黑屏怎么办 枪火游侠闪退怎么办 欧卡2气压过低怎么办 微信安装包己损坏怎么办 qq超市金币累计满了怎么办 我该怎么办?欠了那么多钱? 枪神王座被检测怎么办 酷派大神x7刷机出1004怎么办 水鬼捞锤塌方了怎么办 请事假领导不批怎么办 要请假领导不批怎么办 有急事请假不批怎么办 员工要请假不批怎么办 普法知识竞赛要重新参与怎么办 我被当兵的打怎么办 头发没了一小块怎么办 改革怎么看我该怎么办 笔记本电脑卡死了怎么办关不了机 电脑卡死了怎么办关不了机 火车上别人占座怎么办 火车上遇到占座怎么办 青少年体力差容易疲劳怎么办 四年级的孩子作业拖拉怎么办 四年级孩子不写作业怎么办 四年级孩子不爱写作业怎么办 四年级的孩子写作业慢怎么办 四年级孩子不想写作业怎么办 四年级孩子写作业特别慢怎么办 6岁儿童睡眠少怎么办 四岁儿童睡眠少怎么办 因睡眠不足第二天没有精神怎么办 睡时间久了头疼怎么办 睡不踏实老醒怎么办 运动过后大腿肌肉酸痛怎么办 牛奶喝多了想吐怎么办 运动过度后吐了怎么办 喝酒后反胃想吐怎么办 拔牙后反胃想吐怎么办 健身完恶心想吐怎么办 锻炼后头晕想吐怎么办 高三学生睡眠不好怎么办