大家好,我是小米,今天我们来聊聊Java中两个常见的面试题,特别适合社招面试场景——Callable、Future 和 FutureTask。这三个概念在Java多线程编程中至关重要,掌握它们,你的多线程编程能力将会提升一个大台阶!这不仅能让你在面试中脱颖而出,还能帮你写出更加高效、优雅的多线程代码。 今天我就给大家分享一下这三个概念的理解,并结合真实的代码示例,带你从零到一掌握这些知识。让我们开始吧! 为什么要了解Callable、Future和FutureTask? 首先,很多朋友在接触多线程编程时,通常只了解Thread和Runnable接口的用法。这是因为它们是最基础的多线程操作方式。但在实际开发中,Thread和Runnable提供的功能可能并不能完全满足我们的需求,特别是当我们需要获取线程执行结果或处理任务的异常时,Thread和Runnable就显得力不从心了。 而这时候,Callable、Future 和 FutureTask 就发挥了它们独特的优势。它们是Java提供的高级并发工具,使得多线程编程变得更加灵活、强大。 接下来,我们一一来看这三个概念。 Callable:一个更加强大的任务接口 1、什么是Callable? 在Java中,Callable 接口是 java.util.concurrent 包下的一个接口,它和 Runnable 很相似,都是用来定义一个任务。但是,Callable 有两个明显的优势: 可以返回结果:Runnable接口的run()方法是没有返回值的,这意味着你无法直接从run()中得到计算结果。而Callable接口的call()方法返回一个值,允许你在任务完成时获取任务的执行结果。 支持异常抛出:Runnable的run()方法不能抛出任何异常,而Callable的call()方法可以抛出异常。这就使得我们在执行任务时可以捕获和处理异常,更加灵活。 2、 如何使用Callable? 我们来看一个简单的例子,展示如何使用Callable接口。
在这个例子中,MyCallable 实现了 Callable 接口,并重写了 call() 方法,返回了一个整数 123。我们通过直接调用 call() 方法来执行任务,并获得返回结果。 Future:任务的结果包装器 1、什么是Future? 在多线程编程中,Future 接口的作用是表示一个异步计算的结果。简单来说,它就是一个用于获取异步任务执行结果的对象。 Future 接口有以下几个关键方法: get():阻塞当前线程,直到任务完成并返回结果。 cancel():取消任务的执行。 isDone():检查任务是否已经完成。 isCancelled():检查任务是否已经被取消。 Future 和 Callable 是密切相关的。你可以通过 ExecutorService 提交一个 Callable 任务,获取一个 Future 对象,这样就可以在将来某个时间点得到任务的执行结果。 2、如何使用Future? 我们通过一个简单的例子来说明:
在这个例子中,我们通过 ExecutorService 提交了一个 Callable 任务,并获得了一个 Future 对象。接着,我们调用 future.get() 来阻塞当前线程,直到任务执行完成并返回结果。结果是 123,这就是通过 Future 获取到的。 3、 需要注意的是 Future.get() 方法是阻塞的,也就是说,它会阻塞调用线程直到任务完成。如果任务没有完成,这个调用会一直等待下去,直到任务完成或发生异常。如果你想设置一个超时时间,可以使用 get(long timeout, TimeUnit unit) 方法。 FutureTask:Callable与Future的结合体 1、什么是FutureTask? FutureTask 是一个既实现了 Callable 接口,又实现了 Future 接口的类。它实际上是一个可以被多个线程执行的任务,并且可以获取执行结果或处理异常。 你可以把 FutureTask 看作是 Callable 和 Future 的结合体。使用 FutureTask,你不仅可以像使用 Callable 一样定义任务,还能像使用 Future 一样获取任务的结果。 2、如何使用FutureTask?
在这个例子中,FutureTask 既可以作为任务的执行者,又可以作为获取结果的载体。我们通过 new Thread(futureTask).start() 来启动任务,并通过 futureTask.get() 获取任务的执行结果。 Callable、Future和FutureTask的区别与联系 1、区别 Callable:是一个接口,定义了任务的执行方法 call(),返回任务的结果。 Future:也是一个接口,表示异步计算的结果,通过 get() 方法获取结果。 FutureTask:是 Callable 和 Future 的实现,既可以作为任务执行,又可以获取任务结果。 2、联系 Callable 用于定义任务,Future 用于获取任务的结果,而 FutureTask 将二者结合起来,提供了更为方便的功能。 在多线程中,通常通过 ExecutorService.submit() 方法提交 Callable 任务,得到 Future 对象。如果你希望直接执行任务并获取结果,可以使用 FutureTask。 END 今天我们讲解了Callable、Future 和 FutureTask 这三个概念。在实际的开发过程中,它们帮助我们更加灵活、高效地处理多线程任务。通过它们,我们可以: 使用 Callable 来定义有返回值且可能抛出异常的任务。 使用 Future 来获取任务的执行结果,并提供取消任务和检查任务状态的功能。 使用 FutureTask 来结合 Callable 和 Future,提供一个可执行且可以获取结果的任务。 希望大家通过这篇文章对这三个概念有了更加清晰的理解。如果你对Java多线程有更深入的兴趣,欢迎留言与我交流,我们一起进步! 以上就是今天的分享,感谢大家的阅读,我们下次见! 我是小米,一个喜欢分享技术的29岁程序员。如果你喜欢我的文章,欢迎关注我的微信公众号“软件求生”,获取更多技术干货!