java.util.concurrent.Callable接口是JDK1.5的时候引入的,相比较前两种实现多线程的方式,通过实现Callable接口实现多线程会更麻烦,但是此接口的最大特点是线程主体执行完毕之后会有返回值。
观察Callable接口的定义:
@FunctionalInterface public interface Callable<V>{ public V call() throws Exception ; }call()方法执行完线程的主体功能之后可以返回一个结果,而这个结果的类型是由Callable接口上的泛型来决定。 定义一个线程主体类: import java.util.concurrent.Callable ;//需要导包 class MyThread implements Callable<String>{ private int tickets = 10 ; @Override public String call() throws Exception{ for(int x = 0 ; x < tickets ; x ++){ if(tickets > 0 ){ System.out.println("卖票,tickets = " + this.tickets --) ; } } return "票已卖光" ; } }Runnable接口启动多线程靠的是Thread类。观察Thead类里面发现并没有直接支持Callable接口的多线程应用。从JDK1.5开始,引入了java.util.concurrent.FutureTask<v>类,这个类的主要功能是负责Callable接口对象操作的,观察这个类的定义结构:
public class FutureTask<V>extends Object implements RunnableFuture<V>发现这个类实现了一个叫做RunnableFuture<V>的接口,观察这个接口的定义: public interface RunnableFuture<V> extends Runnable, Future<V>可以发现RunnableFuture接口实现了Runnable接口,那么我们就可以使用Thread类来启动多线程了
在FutureTask<V>类里面有这样一个构造方法:
public FutureTask(Callable<V> callable) ;这个构造方法可以接收Callable接口对象,接收的目的是取得call()方法的返回结果。因为FutureTask<V>这个类可以接收Callable接口对象,并且FutureTask<V>类是Runnable接口的子类,那么我们就可以通过Thread类来启动多线程。
启动多线程:
public class Demo{ public static void main (String [] args) throws Exception{ MyThread m1 = new MyThread () ; MyThread m2 = new MyThread () ; FutureTask<String> f1 = new FutureTask<String>(m1) ;//目的是为了取得call()方法的返回值 FutureTask<String> f2 = new FutureTask<String>(m2) ;//目的是为了取得call()方法的返回值 //FutureTask类是Runnable接口的子类,所以可以使用Thread类的构造来接收FutureTask的实例化对象 new Thread(f1).start() ; new Thread(f2).start() ; //多线程执行完毕后可以取得返回值,依靠FutureTask的父接口Future中的get()方法完成 System.out.println("线程1的返回结果:" + f1.get()) ; System.out.println("线程2的返回结果:" + f2.get()) ; } }注意:这段代码需要进行导包操作:import java.util.concurrent.FutureTask ;