文章目录
- 1、Callable概述
- 2、FutureTask
Java基础中,了解到的创建线程的两种方式为:
- 继承Thread类
- 实现Runnable接口
除了以上两种,还可以通过:
- Callable接口(since JDK1.5)
- 线程池方式
1、Callable概述
前面的Thread类或者Runnable接口方式创建线程,线程终止时,即run方法运行结束时,无法使线程返回结果,而Callable接口的优势正在于此。

而java.lang.Runnable是void run( ) 方法:

查看文档可以发现Thread的构造方法中,没有传Callable类型形参的,那就找个中间类:

 Thread可以传入Runnable,Runnable有个实现类叫FutureTask,它的构造方法可以传Callable,这就是个Thread和Callable的中间人。

2、FutureTask
传入一个可调用的任务对象Callable,创建一个 FutureTask,一旦运行就执行给定的 Callable。
public FutureTask(Callable<V> callable)
关于FutureTask的理解,就是一个可取消的异步计算,单开一个线程去干其他事儿,到时候活儿干完了我在其它线程获取结果就行。这一点在之前的Runnable是实现不了的,它的run方法是void类型。
举个现实生活的例子:
老师在上课(线程A),突然口渴了(需要有一个其他计算任务),但老师不好停下课中途去买水,于是让班长一个人出去给他买水(单开一个线程),他继续上课,等班长回来,他就直接喝(计算完成后,在当前线程直接get另一线程的运行结果)。当然老师可能中途想到万一遇到校长就不妙了,于是在窗外喊住了班长,不让买了(计算结果未完成前,可以取消结果),也可能中途是想告诉班长不买水了,买包烟,于是也在窗外喊住了班长(计算结果未完成前,可以重新开始)。当然,如果这之前班长已经卖回来了,那老师就只能喝水了(一旦计算完成,就不能再重新开始或取消计算)。
FutureTask类的常用方法
- 取消计算,若无法取消任务,则返回 false
public boolean cancel(boolean mayInterruptIfRunning)
- 查询计算是否完成,FutureTask正常终止、异常或取消而完成均返回true
public boolean isDone()
- 获取计算结果
public V get()
//重载,可传入一个最大等待时间
写个demo:
/**
 * Runnable
 */
class MyThread1 implements Runnable{
    @Override
    public void run() {
    }
}
/**
 * Callable
 */
class MyThread implements Callable<String>{
    @Override
    public String call() throws Exception {
        return "200";
    }
}
public class Demo1 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
    
        FutureTask<String> futureTask1 = new FutureTask<>(new MyThread());
        
        FutureTask<String> futureTask2 = new FutureTask<>(() -> {
            System.out.println(Thread.currentThread().getName() + " --> come in callable");
            return "1024";
        });
        
        new Thread(futureTask2,"t1").start();
        
        while (!futureTask2.isDone()){   //futuretask2未计算完成前,一直打印wait....
            System.out.println("wait.......");
        }
        
        System.out.println(futureTask2.get());  //在主线程中首次获取futuretask2所在线程的计算结果
        
        System.out.println(futureTask2.get());   //第二次获取计算结果
        
        System.out.println(Thread.currentThread().getName() + " --> come over");
    }
}
运行:

在其他FutureTask所在线程中获取下另外FutureTask所在线程的计算结果:
/**
 * Callable
 */
class MyThread2 implements Callable<String>{
    @Override
    public String call() throws Exception {
        System.out.println(Thread.currentThread().getName() + " --> come in callable");
        return "200";
    }
}
public class Demo1 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        FutureTask<String> futureTask1 = new FutureTask<>(new MyThread2());
        FutureTask<String> futureTask2 = new FutureTask<>(() -> {
            System.out.println(Thread.currentThread().getName() + " --> come in callable");
            System.out.println("在futureTask1所在线程中获取futureTask1所在线程的计算结果:" + futureTask1.get());
            return "1024";
        });
        new Thread(futureTask1,"t1").start();
        new Thread(futureTask2,"t2").start();
        System.out.println("在main线程中获取futureTask1所在线程的计算结果:" + futureTask1.get());
        System.out.println("在main线程中获取futureTask2所在线程的计算结果:" + futureTask2.get());
        System.out.println(Thread.currentThread().getName() + " --> come over");
    }
}
运行:




















