java面试中,面试官会问,实现多线程有几种方式,答:两种,继承Thread类,实现runnable接口,面试官:开门,左转,不送。开个玩笑,实现多线程只知道这两种方式是不够的,今天我们就来介绍下,实现多线程的第三种方式,Callable,它也是JUC包下的接口,它的主要特点是带返回值,而且抛出异常,返回值类型在实现Callable接口时泛型指定,下边是Callable接口的源代码,这里泛型<V>就是指定返回值的类型。
package java.util.concurrent;
@FunctionalInterface
public interface Callable<V> {
/**
* Computes a result, or throws an exception if unable to do so.
*
* @return computed result
* @throws Exception if unable to compute a result
*/
V call() throws Exception;
}
主要和JUC包下的FutureTask类合起来用,java.util.concurrent.FutureTask,翻译成未来任务,是把比较耗费时间的处理重新开一个线程去执行,等任务结束后,主线程来获取返回值使用,这里有个不成文的规定,futureTask.get()方法建议放到main线程的最后,因为futureTask中没有计算完成,会导致线程阻塞,直到计算完成,接下来我们看一个demo。
在main线程中,开启一个实现Callable接口的线程类,在线程类中有一个返回1024的方法,并配合FutureTask类来使用,最后在主线程获取该线程的返回值1024。
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;public class CallAbleDemo {
public static void main(String[] args) throws Exception {
FutureTask<Integer> futureTask = new FutureTask<>(new MyThread());
Thread t1 = new Thread(futureTask, "t1");
t1.start();System.err.println("***********************result=" + futureTask.get());
}
}
class MyThread implements Callable<Integer> {
@Override
public Integer call() throws Exception {
TimeUnit.SECONDS.sleep(2);
System.err.println("***********************call method invoked... ");
return 1024;
}}
执行结果
***********************call method invoked...
***********************result=1024
不是很复杂把,大家可以动手试试,Callable用在什么场景上呢,假设我们在一个main线程中,开了10个线程,我们想知道每个线程执行成功还是执行失败,在每个线程中设定一个返回值,成功返回true,失败返回false,再比如,计算非常耗时并返回计算结果,类似有这样需求的话,可以使用实现Callable接口的线程类,今天说到实现多线程的第三种方式,那么实现多线程有没有第四种方式呢,我们后续再聊吧,下篇见。