Runnable实现的是void run()方法,可以提交给Thread来包装下,直接启动一个线程来执行;

Callable实现的是 V call()方法,并且可以返回执行结果,一般都是提交给ExecuteService来执行。

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

// 创建一个执行任务的服务  
ExecutorService executor = Executors.newFixedThreadPool(3); 
//1.Runnable通过Future返回结果为空  
//创建一个Runnable,来调度,等待任务执行完毕,取得返回结果  
Future<?> runnable1 = executor.submit(new Runnable() {  
     @Override  
     public void run() {  
            System.out.println("runnable1 running.");  
     }  
 });  
 //线程会阻塞在这里,执行结束后返回null
 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());  

FutureTask是Future和Callable的结合体,有一个回调函数protected void done(),当任务结束时,该回调函数会被触发。因此,只需重载该函数,即可实现在线程刚结束时就做一些事情。

public class Test {
    public static void main(String[] args) {
        ExecutorService executor = Executors.newCachedThreadPool();
        for(int i=0; i<5; i++) {
            Callable<String> c = new Task();
            MyFutureTask ft = new MyFutureTask(c);
            executor.submit(ft);
        }
        executor.shutdown();
    }

}

class MyFutureTask extends FutureTask<String> {

    public MyFutureTask(Callable<String> callable) {
        super(callable);
    }

    @Override
    protected void done() {
        try {
            System.out.println(get() + " 线程执行完毕!~");
        } catch (InterruptedException | ExecutionException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }


}

class Task implements Callable<String> {

    @Override
    public String call() throws Exception {
        Random rand = new Random();
        TimeUnit.SECONDS.sleep(rand.nextInt(12));
        return Thread.currentThread().getName();
    }
}

参考连接:http://blog.csdn.net/andycpp/article/details/8902655

http://blog.csdn.net/zhangzhaokun/article/details/6615454

标签: none

添加新评论