使用Runnable接口实现的多线程可以避免单线程继承局限,但是Runnable接口实现的多线程会存在一个问题:Runnable接口里面run()方法不能返回操作的结果,所以为了解决这样的问题,从JDK1.5开始对于多线程的实现提供了一个新的接口:java.util.concurrent.Callable,此接口定义如下:
@FunctionalInterface
public interface Callable<V> {
public V call() throws Exception ;
}
Callable接口定义的时候可以设置一个泛型,此泛型的类型就是call()方法的返回数据类型,这样的好处是可以避免向下转型带来的安全隐患。
范例:定义线程主体类
import java.util.concurrent.Callable;
public class MyThread310 implements Callable<String> { //线程主体类
@Override
public String call() throws Exception { //线程执行方法
for(int x=0;x<10;x++) {
System.out.println("线程执行x="+x);
}
return "www.Callable.com"; //返回结果
}
}
线程类定义完成后如果要进行多线程的启动仍然需要通过Thread类实现,所以此时可以通过java.util.concurrent.FutureTask类实现Callable 接口与Thread类之间的联系,并且也可以通过FutureTask类获取Callable接口中call()方法的返回值。
Callable与FutureTask
FutureTask类的常用方法
通过FutureTask类继承结构可以发现他是Runnable接口的子类,并且FutureTask类可以接收Callable接口实例,这样依然可以利用Thread类来实现多线程的启动,而如果要想接收返回结果,则利用Funture接口中的get()方法即可。
范例:启动线程并获取Callable返回值
public class ThreadDemo311 {
public static void main(String[] args) throws InterruptedException, ExecutionException {
// 将Callable实例包装在FutureTask类之中,这样可以就可以与Runnable接口关联
FutureTask<String> task=new FutureTask<>(new MyThread310());
new Thread(task).start(); //线程启动
System.out.println("【线程返回数据】"+task.get()); //获得返回结果
}
}
执行结果
线程执行x=0
线程执行x=1
线程执行x=2
线程执行x=3
线程执行x=4
线程执行x=5
线程执行x=6
线程执行x=7
线程执行x=8
线程执行x=9
【线程返回数据】www.Callable.com
Runnable与Callable的区别
- Runnable是在jdk1.0提出,Callable是在jdk1.5提出
- Runnable接口中只提供一个run方法,并且没有返回值
- Callable接口提供有call()方法,可以有返回值。通过Future接口获取。