`

Runnable、Callable、Executor、Future、FutureTask关系解读

阅读更多
转自:http://blog.csdn.net/zhangzhaokun/article/details/6615454

在再度温习Java5的并发编程的知识点时发现,首要的就是把Runnable、Callable、Executor、Future等的关系搞明白,遂有了下述小测试程序,通过这个例子上述三者的关系就一目了然了。

在java5以后,一个可以调度执行的线程单元可以有三种方式定义:

Thread、Runnable、Callable,其中Runnable实现的是void run()方法,Callable实现的是 V call()方法,并且可以返回执行结果,其中Runnable可以提交给Thread来包装下,直接启动一个线程来执行,而Callable则一般都是提交给ExecuteService来执行。

简单来说,Executor就是Runnable和Callable的调度容器,Future就是对于具体的调度任务的执行结果进行查看,最为关键的是Future可以检查对应的任务是否已经完成,也可以阻塞在get方法上一直等待任务返回结果。Runnable和Callable的差别就是Runnable是没有结果可以返回的,就算是通过Future也看不到任务调度的结果的。

/** 
 * 通过简单的测试程序来试验Runnable、Callable通过Executor来调度的时候与Future的关系 
 */  
package com.hadoop.thread;  
  
import java.util.concurrent.Callable;  
import java.util.concurrent.ExecutorService;  
import java.util.concurrent.Executors;  
import java.util.concurrent.Future;  
  
public class RunnableAndCallable2Future {  
  
    public static void main(String[] args) {  
  
        // 创建一个执行任务的服务  
        ExecutorService executor = Executors.newFixedThreadPool(3);  
        try {  
            //1.Runnable通过Future返回结果为空  
            //创建一个Runnable,来调度,等待任务执行完毕,取得返回结果  
            Future<?> runnable1 = executor.submit(new Runnable() {  
                @Override  
                public void run() {  
                    System.out.println("runnable1 running.");  
                }  
            });  
            System.out.println("Runnable1:" + runnable1.get());  
  
            // 2.Callable通过Future能返回结果  
            //提交并执行任务,任务启动时返回了一个 Future对象,  
            // 如果想得到任务执行的结果或者是异常可对这个Future对象进行操作  
            Future<String> future1 = executor.submit(new Callable<String>() {  
                @Override  
                public String call() throws Exception {  
                    // TODO Auto-generated method stub  
                    return "result=task1";  
                }  
            });  
            // 获得任务的结果,如果调用get方法,当前线程会等待任务执行完毕后才往下执行  
            System.out.println("task1: " + future1.get());  
  
            //3. 对Callable调用cancel可以对对该任务进行中断  
            //提交并执行任务,任务启动时返回了一个 Future对象,  
            // 如果想得到任务执行的结果或者是异常可对这个Future对象进行操作  
            Future<String> future2 = executor.submit(new Callable<String>() {  
                @Override  
                public String call() throws Exception {               
                    try {  
                        while (true) {  
                            System.out.println("task2 running.");  
                            Thread.sleep(50);  
                        }  
                    } catch (InterruptedException e) {  
                        System.out.println("Interrupted task2.");  
                    }  
                    return "task2=false";  
                }  
            });  
              
            // 等待5秒后,再停止第二个任务。因为第二个任务进行的是无限循环  
            Thread.sleep(10);  
            System.out.println("task2 cancel: " + future2.cancel(true));  
  
            // 4.用Callable时抛出异常则Future什么也取不到了  
            // 获取第三个任务的输出,因为执行第三个任务会引起异常  
            // 所以下面的语句将引起异常的抛出  
            Future<String> future3 = executor.submit(new Callable<String>() {  
  
                @Override  
                public String call() throws Exception {  
                    throw new Exception("task3 throw exception!");  
                }  
  
            });  
            System.out.println("task3: " + future3.get());  
        } catch (Exception e) {  
            System.out.println(e.toString());  
        }  
        // 停止任务执行服务  
        executor.shutdownNow();  
    }  
}  

执行结果如下:

runnable1 running. 
Runnable1:null 
task1: result=task1 
task2 running. 
task2 cancel: true 
Interrupted task2. 
java.util.concurrent.ExecutionException: java.lang.Exception: Bad flag value! 
FutureTask则是一个RunnableFuture<V>,即实现了Runnbale又实现了Futrue<V>这两个接口,另外它还可以包装Runnable和Callable<V>,所以一般来讲是一个符合体了,它可以通过Thread包装来直接执行,也可以提交给ExecuteService来执行,并且还可以通过v get()返回执行结果,在线程体没有执行完成的时候,主线程一直阻塞等待,执行完则直接返回结果。

public class FutureTaskTest {  
  
    /** 
     * @param args 
     */  
    public static void main(String[] args) {  
        Callable<String> task = new Callable<String>() {  
            public String call() {  
                System.out.println("Sleep start.");  
                try {  
                    Thread.sleep(1000 * 10);  
                } catch (InterruptedException e) {  
                    // TODO Auto-generated catch block  
                    e.printStackTrace();  
                }  
                System.out.println("Sleep end.");  
                return "time=" + System.currentTimeMillis();  
            }  
        };  
          
        //直接使用Thread的方式执行  
        FutureTask<String> ft = new FutureTask<String>(task);  
        Thread t = new Thread(ft);  
        t.start();  
        try {  
            System.out.println("waiting execute result");  
            System.out.println("result = " + ft.get());  
        } catch (InterruptedException e) {  
            // TODO Auto-generated catch block  
            e.printStackTrace();  
        } catch (ExecutionException e) {  
            // TODO Auto-generated catch block  
            e.printStackTrace();  
        }  
          
        //使用Executors来执行  
        System.out.println("=========");  
        FutureTask<String> ft2 = new FutureTask<String>(task);  
        Executors.newSingleThreadExecutor().submit(ft2);  
        try {  
            System.out.println("waiting execute result");  
            System.out.println("result = " + ft2.get());  
        } catch (InterruptedException e) {  
            // TODO Auto-generated catch block  
            e.printStackTrace();  
        } catch (ExecutionException e) {  
            // TODO Auto-generated catch block  
            e.printStackTrace();  
        }  
          
    }  
}  

执行结果如下:

waiting execute result 
Sleep start. 
Sleep end. 
result = time=1370844662537 
========= 
waiting execute result 
Sleep start. 
Sleep end. 
result = time=1370844672542 
分享到:
评论
1 楼 txxxs 2016-04-09  
good,bucuo

相关推荐

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

    主要介绍了Java中的Runnable,Callable,Future,FutureTask的比较的相关资料,需要的朋友可以参考下

    【并发编程】 — 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 ...

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

    http://blog.csdn.net/yangzhaomuma/article/details/51722779

    Callable和Future.doc

    Callable和Future详解: Callable和Runnable有几点不同: (1)Callable规定的方法是call(),而Runnable规定的方法是run(); (2)call()方法可抛出异常,而run()方法是不能抛出异常的。 (3)Runnable不会返回结果,...

    使用Runnable模拟Callable接口实现线程有返回值

    大家都知道Runnable和Callable接口都可以作为其他线程执行的任务,但是Runnable接口的run方法没有返回值,而Callable接口的call方法有返回值,那么Callable接口是如何做到的呢?在此我给出一个Demo,看看通过...

    Java 线程对比(Thread,Runnable,Callable)实例详解

    主要介绍了Java 线程(Thread,Runnable,Callable)实例详解的相关资料,这里对java 线程的三种方法进行了对比,需要的朋友可以参考下

    MapReduce,泛型,匿名内部类,Runnable和Callable

    NULL 博文链接:https://pengqb.iteye.com/blog/738210

    这就是标题—— JUC.pdf

    callable / runnable FutureTask JUC常用辅助类 CountDownLatch (减少计数器) CyclicBarrier(加法计数器) Semaphore(信号量,流量控制) ReentrantReadWriteLock (读写锁) BlockingQueue(阻塞队列) 线程池 ...

    面向小白学习法——Thread和Runnable,扩展Callable!

     面向小白学习法——Thread和Runnable,扩展Callable! Thread和Runnable的区别 (Callable扩展)  线程  Thread Runnable  扩展——Callable  面向小白学习法——Thread和Runnable,扩展Callable! Thread和...

    【多线程高并发编程】三 Callable源码分析

    文章目录前言1.Callable的前世今生1.1 Callable的前世Runnable测试结果1.2 Callable的今生通过FutureTask+Thread调用ExecutorService+Future调用实现2.源码分析2.1 第一步,实现Callable接口2.2 FutureTask类结构图...

    java自定义任务类定时执行任务示例 callable和future接口使用方法

    Callable是类似于Runnable的接口,实现Callable接口的类和实现Runnable的类都是可被其它线程执行的任务

    线程池之Executor框架.docx

    包括被执行任务需要实现的接口:Runnable接口或者Callable接口。 任务的执行 。包括任务执行机制的核心接口Executor,以及继承自Executor的ExecutorService接口。Executor框架有两个关键类实现了ExecutorService...

    创建线程的三种方式(Thread、Runnable、Callable).docx

    继承Thread类实现多线程: 1. 在Java中负责实现线程功能的类是java.lang.Thread 类。 2. 可以通过创建 Thread的实例来创建新的线程。 3. 每个线程都是通过某个特定的Thread对象所对应的方法run( )来完成其操作的,...

    java8源码-concurrency:java并发总结

    Runnable Callable Future ExecutorService Class Thread FutureTask FutureTask 获取线程执行结果的原理:以 ThreadPoolExecutor 为例(实现 ExecutorService 接口), 其 submit() 方法提交任务, 返回 一个 ...

    java并发编程:Executor、Executors、ExecutorService.docx

    Executor: 一个接口,其定义了一个接收Runnable对象的方法executor,其方法签名为executor(Runnable command),该方法接收一个Runable实例,它用来执行一个任务,任务即一个实现了Runnable接口的类,一般来说,...

    多线程文章目录

    了解线程的状态、常用方法以及Thread、Runnable、Callable、Future、FutureTask这些基础概念和简单应用。 Java多线程②——多线程知识梳理 有助于了解线程池相关的知识、包括线程池执行逻辑、常用方法; 以及java为...

    线程超时死掉

    不直接构造Future对象,也可以使用ExecutorService.submit方法来获得Future对象,submit方法即支持以 Callable接口类型,也支持Runnable接口作为参数,具有很大的灵活性。使用示例如FutureTaskAndExcutor中的limit...

    Java并发Executor框架

     从JDK5开始,工作单元和执行机制隔离开来,工作单元包括Runnable和Callable,执行机制由Executor提供。  调用关系:Java线程一对一映射到本地操作系统的系统线程,当多线程程序分解若干任务,使用用户级的调度...

Global site tag (gtag.js) - Google Analytics