zoukankan      html  css  js  c++  java
  • Java并发(6)带返回结果的任务执行

    携带结果的任务

    JDK5提供了有可返回值的任务的执行。java.util.concurrent中Callable与Futrue用以实现带返回值的任务执行。

    使用Callable与Futrue与使用Runnable最大的两个区别在于:

    1、Callable/Future是带返回值的;Runnable无法带返回值。

    2、Callable/Future所执行的任务是可取消的。Runnable的任务无法取消。

     

    Callable接口

    Callable 接口类似于 Runnable,两者都是为那些其实例可能被另一个线程执行的类设计的。可返回值的任务必须实现Callable接口。

    public interface Callable<V> {

    V call() throws Exception;

    }

    call()方法用于计算结果,如果无法计算结果,则抛出一个异常。Vcall方法的结果类型。

     

    Callable接口定义了一个call方法可以作为线程的执行体,但call方法比run方法更强大:

        call()方法可以有返回值。

        call()方法可以申明抛出异常。

     

    通过ExecutorSevicesubmit()方法将Callable提交至线程池中执行,submit()方法返回一个Future实例。

    使用CompletionService接口可以用于提交一组Callable任务,其take()方法返回已完成的一个Callable任务对应的Future实例。好比同时种了几块地的麦子,然后就等待收割。收割时,则是那块先成熟了,则先去收割哪块麦子。

     

     

    Futrue接口

    Future 表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并获取计算的结果。如果为了可取消性而使用 Future 但又不提供可用的结果,则可以声明 Future<?> 形式类型、并返回 null 作为底层任务的结果。

    一旦计算完成,就不能再取消计算。

    提交(submit()方法)Callable任务,可以获取一个Future实例。Futrue实例调用get()方法即可获取Callable任务返回值。

    public interface Future<V> {

    boolean cancel(boolean mayInterruptIfRunning);

    boolean isCancelled();

    boolean isDone();

    V get() throws InterruptedException, ExecutionException;

    V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;

    }

     

    Future接口里定义了如下几个公共方法控制他关联的Callable任务:

    V get():返回Callable任务里的call()方法的返回值,调用该方法将导致线程阻塞,必须等到子线程结束才得到返回值。

    V get(long timeout,TimeUnit unit) : 返回Callable任务里的call方法的返回值。该方法让程序最多阻塞timeoutunit指定的时间。如果经过指定时间后Callable任务依然没有返回值,将会抛出TimeoutException

    boolean cancel(boolean mayInterruptlfRunning) :试图取消该Future里关联的Callable任务。

    boolean isCancelled() :如果在Callable任务正常完成前被取消,则返回true

    boolean isDone() :如果Callable任务已经完成,则返回true

     

     

    例:使用Executor框架执行Callable并返回结果。

    import java.util.concurrent.Executors;

    import java.util.concurrent.ExecutorService;

    import java.util.concurrent.*;

    public class Test {

        public static void main(String[] args) throws ExecutionException, InterruptedException {

            // 创建一个线程池

            ExecutorService pool = Executors.newFixedThreadPool(2);

            // 创建两个有返回值的任务

            Callable c1 = new MyCallable("A");

            Callable c2 = new MyCallable("B");

            // 执行任务并获取Future对象

            Future f1 = pool.submit(c1);

            Future f2 = pool.submit(c2);

            // Future对象上获取任务的返回值,并输出到控制台

            System.out.println(">>>" + f1.get().toString());

            System.out.println(">>>" + f2.get().toString());

            // 关闭线程池

            pool.shutdown();

        }

    }

    class MyCallable implements Callable {

        private String oid;

        MyCallable(String oid) {

            this.oid = oid;

        }

        @Override

        public Object call() throws Exception {

            return oid + "任务返回的内容";

        }

    }

     

     

    执行输出结果:

    >>>A任务返回的内容

    >>>B任务返回的内容

     

     

    RunnableFuture接口

    public interface RunnableFuture<V> extends Runnable, Future<V> {

    void run();

    }

    FutrueTask类

    java.util.concurrent.FutureTask<V>

    Future接口的一个实现类。该实现类实现Future接口,并实现了Runnable接口。FutureTask即可以作为Threadtarget

     

    使用FutrueTask执行单个任务。

    创建、并启动有返回值的线程的步骤如下:

    1.创建Callable接口的实现类,实现call方法。

    2.创建Callable实现类的实例,使用FutureTask类来包装Callable对象。

    3.使用FutureTask对象作为Thread对象的target创建、并启动新线程。

    4.调用FutureTask对象的方法来获得子线程执行结束后的返回值。

     

    例:使用FutrueTask类执行Callable并返回结果。

    class RtnThread implements Callable<Integer> {

        public Integer call() {

            // 执行过程

        }

    }

    public class CallableTest {

        public static main(String[] args) {

            // 创建Callable对象。

            RtnThread rt = new RtnThread();

            FutureTask<Integer> task = new FutureTask<Integer>(rt);

            // ..

            // 创建线程,并启动。

            new Thread(task).start();

            // ..

            Integer i = task.get(); // 获取线程返回值。

        }

    }

    创建Callable实现类与创建Runnable实现类并没有太大差别,只是Callablecall允许抛出异常,而且允许带返回值。

     

  • 相关阅读:
    例子:进度条制作
    例子:滑动效果
    例子:选项卡效果
    例子:图片轮播
    9.23 开课第二十天 (事件)
    例子:日期时间选择
    例子:两个列表之间移动数据
    php数据访问基础
    php面向对象加载类、常用设计模式
    php面向对象中的静态与抽象,接口
  • 原文地址:https://www.cnblogs.com/shijiaqi1066/p/3412331.html
Copyright © 2011-2022 走看看