FutureTaske对象(子类)属于 Runnable对象(父类接口),Thread线程有参构造器只能接收Runnable类型的对象(可以接收其子类)
FutureTask 未来任务 的意思
三种线程创建方式的对比:
package com.itheima.d1_create;
import javax.swing.table.TableRowSorter;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
/**
* 目标: 学会线程的创建方式三;实现Callable接口,结合FutureTask(未来任务)完成
*/
public class ThreadDemo03 {
public static void main(String[] args) {
// 3. 创建Callable任务对象
Callable<String> call = new MyCallable(100);
// 4. 把Callable任务对象 交给FutureTask 对象
// FutureTask对象任务的作用1: 是Runnable的对象(实现了Runnable接口),可以交给Thread对象了
// futureTask对象的作用2:可以在线程执行完毕之后通过调用其get方法得到线程执行完成的结果
// 这里就不用多态写了, 因为要调用FuntureTask的子类方法
FutureTask<String> f1 = new FutureTask<>(call); // // 将创建的Callable任务对象 传送给 FutureTask任务对象的有参构造器
// 5. 交给线程处理 (创建线程对象,交给其有参构造器)
Thread t1 = new Thread(f1);
// 6. 启动线程
t1.start();
/**
* 可以再来一个线程任务 该线程计算1 - 2000 的和
*/
// 3. 创建Callable任务对象
Callable<String> call2 = new MyCallable(2000);
// 4. 把Callable任务对象 交给FutureTask 对象
// FutureTask对象任务的作用1: 是Runnable的对象(实现了Runnable接口),可以交给Thread对象了
// futureTask对象的作用2:可以在线程执行完毕之后通过调用其get方法得到线程执行完成的结果
// 这里就不用多态写了, 因为要调用FuntureTask的子类方法
FutureTask<String> f2 = new FutureTask<>(call2); // // 将创建的Callable任务对象 传送给 FutureTask任务对象的有参构造器
// 5. 交给线程处理 (创建线程对象,交给其有参构造器)
Thread t2 = new Thread(f2);
// 6. 启动线程
t2.start();
// 通过未来任务FutureTask的get方法来拿结果,不推荐用Callable接口对象拿结果(可能线程还没执行完)
try {
// 如果f1任务没有执行完毕,这里的代码会等待,直到线程1跑完才会提取结果
String rs = f1.get(); // 该结果要定义一个变量来接收,接收的变量类型和泛型接口一样
System.out.println("第一个结果为:" + rs);
} catch (Exception e) {
e.printStackTrace();
}
// 拿未来任务对象f2的结果
try {
// 如果f2任务没有执行完毕,这里的代码会等待,直到线程2跑完才会提取结果
String rs2 = f2.get(); // 该结果要定义一个变量来接收,接收的变量类型和泛型接口一样
System.out.println("第二个结果为: " + rs2);
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 1. 定义一个任务类,实现Callable接口 应该申明线程任务执行完毕后的结果的数据类型
* Callable 是可呼叫的意思
*/
class MyCallable implements Callable<String>{ // 该接口是一个泛型接口,代表有返回值类型
private int n; // 定义一个 n 的值,然后通过有参构造器赋值给n
public MyCallable(int n) { // 定义一个有参构造器 每次创建该类的对象,就会把n的值,传给该成员
this.n = n;
}
/**
* 重写call 方法 (任务方法,相当于主线程的main方法,表示要干什么)
* @return
* @throws Exception
*/
@Override
public String call() throws Exception {
// 定义该线程任务是求一到n 的和
int sum = 0;
for (int i = 1; i <= n; i++) {
sum += i;
}
return "子线程执行的结果是: " + sum;
}
}