文章目录
- 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");
}
}
运行: