Runable Callable Future

1. Callable与Runable区别

Java从发布的第一个版本开始就可以很方便地编写多线程的应用程序,并在设计中引入异步处理。Thread类、Runnable接口和Java内存管理模型使得多线程编程简单直接。

但Thread类和Runnable接口都不允许声明检查型异常,也不能定义返回值。没有返回值这点稍微有点麻烦。不能声明抛出检查型异常则更麻烦一些。

public void run()方法契约意味着你必须捕获并处理检查型异常。即使你小心地保存了异常信息(在捕获异常时)以便稍后检查,但也不能保证这个类(Runnable对象)的所有使用者都读取异常信息。

你也可以修改Runnable实现的getter,让它们都能抛出任务执行中的异常。但这种方法除了繁琐也不是十分安全可靠,你不能强迫使用者调用这些方法,程序员很可能会调用join()方法等待线程结束然后就不管了。

但是现在不用担心了,以上的问题终于在1.5中解决了。Callable接口和Future接口的引入以及他们对线程池的支持优雅地解决了这两个问题。

不管用哪种方式创建线程,其本质都是Callable接口与Runable接口。两者都是可被其它线程执行的任务!!区别是:

(1)Callable规定的方法是call(),而Runnable规定的方法是run()。

(2)Callable的任务执行后可返回值,而Runnable的任务是不能返回值的。

(3)call()方法可抛出异常,而run()方法是不能抛出异常的。

(4)运行Callable任务可拿到一个Future对象。

2.Future

如上所说,Callable任务返回Future对象。即:Callable和Future一个产生结果,一个拿到结果。

Future 表示异步计算的结果。Future接口中有如下方法:

  •     boolean cancel(boolean mayInterruptIfRunning)

取消任务的执行。参数指定是否立即中断任务执行,或者等等任务结束

  •     boolean isCancelled() 

任务是否已经取消,任务正常完成前将其取消,则返回 true

  •     boolean isDone()

任务是否已经完成。需要注意的是如果任务正常终止、异常或取消,都将返回true

  •     V get()

等待任务执行结束,然后获得V类型的结果。InterruptedException 线程被中断异常, ExecutionException任务执行异常,如果任务被取消,还会抛出CancellationException

  •     V get(long timeout, TimeUnit unit) 

同上面的get功能一样,多了设置超时时间。参数timeout指定超时时间,uint指定时间的单位,在枚举类TimeUnit中有相关的定义。如果计算超时,将抛出TimeoutException

Future接口提供方法来检测任务是否被执行完,等待任务执行完获得结果。也可以设置任务执行的超时时间,这个设置超时的方法就是实现Java程序执行超时的关键。

所以,如果需要设定代码执行的最长时间,即超时,可以用Java线程池ExecutorService类配合Future接口来实现

总结:

Runable适用于完全异步的任务,不用操心执行情况,异常出错的。

Callable适用于需要由返回结果的,对执行中的异常要知晓的,需要提交到线程池中。

Future主要是线程池执行Callable任务,返回的结果。它能够中断任务的执行,一直等待结果,或者等待一段时间获取结果。

一个demo

package com.zyf.Future;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class FutureGetTimeOut1 {  
    public static void main(String[] args){  
        int timeout = 2;   
        ExecutorService executor = Executors.newSingleThreadExecutor();  
        Boolean result = false;     
        Future<Boolean> future = executor.submit(new TaskThread("发送请求"));//将任务提交给线程池
        try {     
            result = future.get(timeout, TimeUnit.SECONDS);
           // result = future.get(timeout, TimeUnit.MILLISECONDS); //1
            System.out.println("发送请求任务的返回结果: "+result);  //2
        } catch (InterruptedException e) {  
            System.out.println("线程中断出错。");  
            future.cancel(true);// 中断执行此任务的线程     
        } catch (ExecutionException e) {     
            System.out.println("线程服务出错。");  
            future.cancel(true);
        } catch (TimeoutException e) {// 超时异常     
            System.out.println("超时。");     
            future.cancel(true);  
        }finally{  
            System.out.println("线程服务关闭。");  
            executor.shutdown();  
        }  
    }  
      
    static class TaskThread implements Callable<Boolean> {    
        private String t;  
        public TaskThread(String temp){  
            this.t= temp;  
        }  
        public Boolean call() {  
            //for用于模拟超时
            for(int i=0;i<999999999;i++){  
                if(i==999999998){  
                    System.out.println(t+"成功!");  
                }  
                if (Thread.interrupted()){ //很重要  
                    return false;     
                }  
            }   
            System.out.println("继续执行..........");     
            return true;     
        }     
    }   
}
发布了504 篇原创文章 · 获赞 610 · 访问量 114万+

猜你喜欢

转载自blog.csdn.net/asdfsadfasdfsa/article/details/103811913