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类型。
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");
}
}
运行: