`

Future、callable和futureTask使用

 
阅读更多
一.Callable与Runnable
  先说一下java.lang.Runnable吧,它是一个接口,在它里面只声明了一个run()方法:

1
2
3
public interface Runnable {
    public abstract void run();
}
  由于run()方法返回值为void类型,所以在执行完任务之后无法返回任何结果。

  Callable位于java.util.concurrent包下,它也是一个接口,在它里面也只声明了一个方法,只不过这个方法叫做call():

1
2
3
4
5
6
7
8
9
public interface Callable<V> {
    /**
     * Computes a result, or throws an exception if unable to do so.
     *
     * @return computed result
     * @throws Exception if unable to compute a result
     */
    V call() throws Exception;
}
  可以看到,这是一个泛型接口,call()函数返回的类型就是传递进来的V类型。

  那么怎么使用Callable呢?一般情况下是配合ExecutorService来使用的,在ExecutorService接口中声明了若干个submit方法的重载版本:

1
2
3
<T> Future<T> submit(Callable<T> task);
<T> Future<T> submit(Runnable task, T result);
Future<?> submit(Runnable task);
  第一个submit方法里面的参数类型就是Callable。

  暂时只需要知道Callable一般是和ExecutorService配合来使用的,具体的使用方法讲在后面讲述。

  一般情况下我们使用第一个submit方法和第三个submit方法,第二个submit方法很少使用。

二.Future
  Future就是对于具体的Runnable或者Callable任务的执行结果进行取消、查询是否完成、获取结果。必要时可以通过get方法获取执行结果,该方法会阻塞直到任务返回结果。

  Future类位于java.util.concurrent包下,它是一个接口:

1
2
3
4
5
6
7
8
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接口中声明了5个方法,下面依次解释每个方法的作用:

cancel方法用来取消任务,如果取消任务成功则返回true,如果取消任务失败则返回false。参数mayInterruptIfRunning表示是否允许取消正在执行却没有执行完毕的任务,如果设置true,则表示可以取消正在执行过程中的任务。如果任务已经完成,则无论mayInterruptIfRunning为true还是false,此方法肯定返回false,即如果取消已经完成的任务会返回false;如果任务正在执行,若mayInterruptIfRunning设置为true,则返回true,若mayInterruptIfRunning设置为false,则返回false;如果任务还没有执行,则无论mayInterruptIfRunning为true还是false,肯定返回true。
isCancelled方法表示任务是否被取消成功,如果在任务正常完成前被取消成功,则返回 true。
isDone方法表示任务是否已经完成,若任务完成,则返回true;
get()方法用来获取执行结果,这个方法会产生阻塞,会一直等到任务执行完毕才返回;
get(long timeout, TimeUnit unit)用来获取执行结果,如果在指定时间内,还没获取到结果,就直接返回null。
  也就是说Future提供了三种功能:

  1)判断任务是否完成;

  2)能够中断任务;

  3)能够获取任务执行结果。

  因为Future只是一个接口,所以是无法直接用来创建对象使用的,因此就有了下面的FutureTask。

三.FutureTask
  我们先来看一下FutureTask的实现:

1
public class FutureTask<V> implements RunnableFuture<V>
  FutureTask类实现了RunnableFuture接口,我们看一下RunnableFuture接口的实现:

1
2
3
public interface RunnableFuture<V> extends Runnable, Future<V> {
    void run();
}
  可以看出RunnableFuture继承了Runnable接口和Future接口,而FutureTask实现了RunnableFuture接口。所以它既可以作为Runnable被线程执行(当作线程时自动调用run方法),又可以作为Future得到Callable的返回值。

  FutureTask提供了2个构造器:

1
2
3
4
public FutureTask(Callable<V> callable) {
}
public FutureTask(Runnable runnable, V result) {
}
  事实上,FutureTask是Future接口的一个唯一实现类。

四.使用示例
  1.使用Callable+Future获取执行结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public class Test {
    public static void main(String[] args) {
        ExecutorService executor = Executors.newCachedThreadPool();
        Task task = new Task();
        Future<Integer> result = executor.submit(task);
        executor.shutdown();
        
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e1) {
            e1.printStackTrace();
        }
        
        System.out.println("主线程在执行任务");
        
        try {
            System.out.println("task运行结果"+result.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        
        System.out.println("所有任务执行完毕");
    }
}
class Task implements Callable<Integer>{
    @Override
    public Integer call() throws Exception {
        System.out.println("子线程在进行计算");
        Thread.sleep(3000);
        int sum = 0;
        for(int i=0;i<100;i++)
            sum += i;
        return sum;
    }
}
  执行结果:

View Code
  2.使用Callable+FutureTask获取执行结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
public class Test {
    public static void main(String[] args) {
        //第一种方式
        ExecutorService executor = Executors.newCachedThreadPool();
        Task task = new Task();
        FutureTask<Integer> futureTask = new FutureTask<Integer>(task);
        executor.submit(futureTask);
        executor.shutdown();
        
        //第二种方式,注意这种方式和第一种方式效果是类似的,只不过一个使用的是ExecutorService,一个使用的是Thread
        /*Task task = new Task();
        FutureTask<Integer> futureTask = new FutureTask<Integer>(task);
        Thread thread = new Thread(futureTask);
        thread.start();*/
        
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e1) {
            e1.printStackTrace();
        }
        
        System.out.println("主线程在执行任务");
        
        try {
            System.out.println("task运行结果"+futureTask.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        
        System.out.println("所有任务执行完毕");
    }
}
class Task implements Callable<Integer>{
    @Override
    public Integer call() throws Exception {
        System.out.println("子线程在进行计算");
        Thread.sleep(3000);
        int sum = 0;
        for(int i=0;i<100;i++)
            sum += i;
        return sum;
    }
}
  如果为了可取消性而使用 Future 但又不提供可用的结果,则可以声明 Future<?> 形式类型、并返回 null 作为底层任务的结果。

转载地址:http://www.cnblogs.com/dolphin0520/p/3949310.html
分享到:
评论

相关推荐

    Java中的Runnable,Callable,Future,FutureTask的比较

    在实际开发中,ExecutorService(如ThreadPoolExecutor)经常与Future和FutureTask一起使用,因为ExecutorService可以提交Runnable或Callable任务,并返回Future,从而实现对任务的异步处理和结果获取。例如: ```...

    Android(Java)之多线程结果返回——Future 、FutureTask、Callable、Runnable

    `Future`、`FutureTask`、`Callable`和`Runnable`是Java并发编程中的核心接口和类,它们在Android开发中同样有着广泛的应用。下面将详细介绍这些概念以及它们如何协同工作。 1. `Runnable`: 这是Java中最基础的多...

    Java使用Callable和Future创建线程操作示例

    Java使用Callable和Future创建线程操作示例主要介绍了Java使用Callable和Future创建线程操作,结合实例形式分析了java使用Callable接口和Future类创建线程的相关操作技巧与注意事项。 首先,Java 5开始,Java提供了...

    比较java中Future与FutureTask之间的关系

    本文将详细介绍Future和FutureTask的关系、使用和分析。 一、Future介绍 Future位于java.util.concurrent包下,是一个接口,定义了五个方法: 1. `cancel(boolean mayInterruptIfRunning)`: 取消任务,取消成功则...

    Runnable、Callable、Future、FutureTask有什么关联.docx

    Runnable、Callable、Future、FutureTask有什么关联.docx

    【并发编程】 — Runnable、Callable、Future和FutureTask之间的关系

    2 如何使用FutureTask 、Future、Callable、线程池实现线程2.1 FutureTask + Callable实现多线程2.2 线程池+Future+Callable 实现多线程3 Runnable、Callable、Future和FutureTask之间的关系3.1 整体关系介绍3.2 ...

    Callable, Future, FutureTask2

    通过合规策略对服务器进行监控,确保服务器的运行、帐号在服务器上的操作符合预设的规则...进程:监控服务器上的进程,并对某些进程、目录、文件进行标识和监控,只允许指定的进程对指定目录下的指定格式文件执行写操作

    Callable,Future的使用方式

    Callable,Future的使用方式,里面使用了三种使用方式分别是FutureTask,ExecutorService,ExecutorCompletionService

    java多线程返回值使用示例(callable与futuretask)

    下面是一个使用`Callable`和`FutureTask`的简单示例: ```java import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import ...

    Java中Future、FutureTask原理以及与线程池的搭配使用

    理解`Future`和`FutureTask`的工作原理,以及如何与`ExecutorService`配合使用,是进行高效并发编程的关键。在实际应用中,它们常用于处理耗时计算、异步数据获取等场景,提高了程序的响应性和并发性。

    JAVA中Callable的使用

    如果你需要从多个Callable任务中获取结果,可以使用`FutureTask`。`FutureTask`是`Future`的一个具体实现,它同时也是一个`Runnable`,可以直接提交给ExecutorService。`FutureTask`的构造函数接受一个Callable对象...

    spring线程池ThreadPoolExecutor配置以及FutureTask的使用

    下面是一个使用`ThreadPoolTaskExecutor`和`FutureTask`的例子: ```java ThreadPoolTaskExecutor executor = (ThreadPoolTaskExecutor) context.getBean("threadPoolTaskExecutor"); Callable&lt;Integer&gt; callable ...

    Java多线程下的其他组件之CyclicBarrier、Callable、Future和FutureTask详解

    在Java多线程编程中,CyclicBarrier、Callable、Future和FutureTask是四个重要的组件,它们各自提供了不同的功能,帮助开发者更好地管理和协调并发任务。接下来,我们将深入探讨这些组件的特性和使用方法。 首先,...

    Callable和Future.doc

    Callable 和 Future 是 Java 多线程编程中两个重要的接口,它们在处理异步计算和结果获取方面发挥着关键作用。Callable 与 Runnable 相似,但具有更强大的功能,允许任务返回结果并处理异常。 Callable 接口: ...

    java多线程编程同步器Future和FutureTask解析及代码示例

    在Java并发编程中,通常我们会使用`ExecutorService`来提交任务,而`Future`和`FutureTask`就是与这些任务交互的关键。 首先,`Future`是一个接口,它提供了一种机制来检查异步计算是否完成,以及在计算完成后获取...

    FutureTask学习

    `FutureTask`作为`Runnable`和`Callable`的桥梁,允许我们将一个`Callable`任务提交给`Executor`执行,并在后续代码中通过`FutureTask`的API查询任务状态,获取结果或取消任务。下面将详细介绍`FutureTask`的主要...

    【Java】Callable创建线程用到的适配器模式(csdn)————程序.pdf

    本文将详细解释Callable接口的使用、适配器模式在创建线程中的应用,以及FutureTask在其中的角色。 首先,Callable接口与Runnable接口类似,都是用于创建新线程的接口。但是,Runnable接口的run()方法无返回值,而...

    Java FutureTask类使用案例解析

    FutureTask类的使用案例主要有两种,一种是使用Callable对象,另一种是使用Runnable对象。使用Callable对象可以获取计算结果,而使用Runnable对象则不能获取计算结果。 在使用FutureTask时,需要注意以下几点: 1....

    浅谈在Java中使用Callable、Future进行并行编程

    总的来说,Callable和Future的结合使用,提供了更强大和灵活的并行编程能力。Callable使得并行任务可以返回结果,而Future则提供了管理和控制这些任务的能力,如检查任务状态、取消任务和获取结果。这种模式在多线程...

    揭密FutureTask.docx

    - `run()`:这是FutureTask实际执行的任务,调用了Callable的`call()`方法,同时更新状态和结果。 - `get()`和`get(long timeout, TimeUnit unit)`:这两个方法会阻塞当前线程,直到任务完成。如果任务已完成,它们...

Global site tag (gtag.js) - Google Analytics