侧边栏壁纸
博主头像
MD_Tech_博客

行动起来,活在当下

  • 累计撰写 8 篇文章
  • 累计创建 8 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

Callable接口详解

Siuux_7
2025-03-10 / 0 评论 / 0 点赞 / 8 阅读 / 0 字

Callable接口

Callable接口是Java 5引入的一个泛型接口,位于java.util.concurrent包中。它与Runnable接口类似,都是用来表示一个可以异步执行的任务。不同的是,Callable可以返回一个结果,并且能够抛出异常。

public interface Callable<V> {  
    V call() throws Exception;  
}

Callable接口只有一个call()方法,该方法返回一个泛型类型V的结果,并且可以抛出Exception异常。

Callable与Runnable

CallableRunnable接口都可以用来创建线程任务。Runnable接口中只有一个run()方法

public interface Runnable {  
	public abstract void run();  
}

看源码可知实现Runnable接口的线程方法没有返回值,也不能抛出异常。而实现Callable接口的线程方法可以返回一个泛型类型V的结果,并且可以抛出异常。

使用场景:

  • Runnable通常用于不需要返回结果的场景,比如简单的异步任务。
  • Callable则用于需要返回结果或需要处理异常的场景。

Future接口

Callable接口通常与Future接口一起使用。Future表示一个异步计算的结果,它提供了检查计算是否完成的方法,以及获取计算结果的方法。

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。

FutureTask类

FutureTask 类实现了RunnableFuture<V>接口,先来看一下RunnableFuture接口

public interface RunnableFuture<V> extends Runnable, Future<V> {  
  void run();  
}

RunnableFuture接口继承了Runnable和Future接口,所以它即可以作为Runnable被线程执行,又可以作为Future得到Callable的返回值

public FutureTask(Callable<V> callable) {  
    if (callable == null)  
        throw new NullPointerException();  
    this.callable = callable;  
    this.state = NEW;        
}

public FutureTask(Runnable runnable, V result) {  
    this.callable = Executors.callable(runnable, result);  //将runnable转换成callable
    this.state = NEW;         
}

事实上,FutureTask是Future接口的一个唯一实现类。

使用示例

  • 当我们提交一个Callable任务给ExecutorService时,它会返回一个Future接口的具体实现类(FutureTask)的对象。通过这个对象,我们可以获取Callable任务的执行结果。
public class test {  
    public static void main(String[] args) throws ExecutionException, InterruptedException {  
        ExecutorService executorService = new ThreadPoolExecutor(  
                2,  
                5,  
                3,  
                TimeUnit.SECONDS,  
                new LinkedBlockingQueue<>(3),  
                Executors.defaultThreadFactory(),  
                new ThreadPoolExecutor.AbortPolicy()  
        );  
        Future<Integer> future = executorService.submit(()->{  
            System.out.println("执行了");  
            return 1024;  
        });  
        Integer result = future.get();  
        System.out.println(result);  
        executorService.shutdown();  
    }  
}
  • 先创建任务,再将任务提交到线程池执行
public class test2 {  
    public static void main(String[] args) throws ExecutionException, InterruptedException {  
        ExecutorService executorService = new ThreadPoolExecutor(  
                2,  
                5,  
                3,  
                TimeUnit.SECONDS,  
                new LinkedBlockingQueue<>(3),  
                Executors.defaultThreadFactory(),  
                new ThreadPoolExecutor.AbortPolicy()  
        );  
  
        FutureTask<Integer> integerFutureTask = null;  
        try {  
            integerFutureTask = new FutureTask<>(() -> {  
                return 1024;  
            });  
            executorService.submit(integerFutureTask);  
            System.out.println(integerFutureTask.get());  
        } catch (Exception e) {  
            throw new RuntimeException(e);  
        } finally {  
            executorService.shutdown();  
        }  
          
    }  
}
  • 直接使用Thred启动线程任务
public class test3 {  
    public static void main(String[] args) throws ExecutionException, InterruptedException {  
        FutureTask<Integer> integerFutureTask = new FutureTask<>(() -> {  
            System.out.println(Thread.currentThread().getName()+"执行了");  
            return 1024;  
        });  
        new Thread(integerFutureTask).start();  
        System.out.println(integerFutureTask.get());  
    }  
}
0

评论区