目录
方式三:实现Callable接口
前言
如何创建
代码实例
API及优缺点
Thread的常用方法
代码演示
方式三:实现Callable接口
前言
前两种线程创建方式都存在的一个问题
- 假如线程执行完毕后有一些数据需要返回,他们重写的run方法均不能直接返回结果。
怎么解决?
- JDK 5.0 提供了Callable接口和FutureTask类来实现(多线程的第三种创建方式)。
- 这种方式最大的优点:可以返回线程执行完毕后的结果。
如何创建
多线程的第三种创建方式:利用Callable接口、FutureTask类来实现。
①:创建任务对象
- 定义一个类实现Callable接口,重写call方法,封装要做的事情,和要返回的数据。
- 把Callable类型的对象封装成FutureTask(线程任务对象)。
②:把线程任务对象交给Thread对象。
③:用Thread对象的start方法启动线程。
④:程执行完毕后、通过FutureTask对象的的get方法去获取线程任务执行的结果。
代码实例
import java.util.concurrent.Callable;
/*
1.让这个类实现Callable接口
*/
public class MyCallable implements Callable<String> {
private int n;
public MyCallable(int n){
this.n = n;
}
//2.重写call方法
@Override
public String call() throws Exception {
//描述线程的任务,返回线程执行返回后的结果
//需求:求1-n的和返回
int sum = 0;
for (int i = 0; i <= n; i++) {
sum += i;
}
return "线程求出了1-" + n + "的和是:" + sum;
}
}
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class ThreadTest4 {
public static void main(String[] args) {
//未来任务对象的作用
//1.是一个任务对象,实现了Runnable对象
//2.可以在线程执行完毕之后,用未来任务对象调用get方法获取线程执行完毕后的结果
//3.创建一个Callable的对象
Callable<String> call = new MyCallable(100);
//4.把Callable的对象封装成一个FutureTask对象(任务对象)
FutureTask<String> f1 = new FutureTask<>(call);
//5.把任务对象交给一个Thread对象
new Thread(f1).start();
//6.获取线程执行完毕后返回的结果
//如果代码执行到这里,上面的线程还没有执行完毕,就会暂停,等待上面线程执行完毕之后才会获取结果
String rs = null;
try {
rs = f1.get();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(rs);
}
}
API及优缺点
FutureTask提供的构造器 | 说明 |
---|---|
public FutureTask<>(Callable call) | 把Callable对象封装成FutureTask对象。 |
FutureTask提供的方法 | 说明 |
---|---|
public V get() throws Exception | 获取线程执行cal1方法返回的结果。 |
线程创建方式三的优缺点
- 优点:线程任务类只是实现接口,可以继续继承类和实现接口,扩展性强;可以在线程执行完毕后去获取线程执行的结果。
- 缺点:编码稍复杂。
Thread的常用方法
Thread提供的常用方法 | 说明 |
---|---|
public void run() | 线程的任务方法 |
public void start() | 启动线程 |
public String getName() | 获取当前线程的名称,线程名称默认是Thread-索引 |
public void setName(String name) | 为线程设置名称 |
public static Thread currentThread() | 获取当前执行的线程对象 |
public static void sleep(long time) | 让当前执行的线程休眠多少毫秒后,再继续执行 |
public final void join()... | 让调用当前这个方法的线程先执行完! |
Thread提供的常见构造器 | 说明 |
---|---|
public Thread(String name) | 可以为当前线程指定名称 |
public Thread(Runnable target) | 封装Runnable对象成为线程对象 |
public Thread(Runnable target,String name) | 封装Runnable对象成为线程对象,并指定线程名称 |
代码演示
public static Thread currentThread() |
public class MyThread extends Thread{
@Override
public void run(){
//哪个线程执行它,它就会得到哪个线程对象
Thread t = Thread.currentThread();
for(int i = 1;i <= 3;i++){
System.out.println( t.getName() + "输出:" + i);
}
}
}
public String getName() |
public class ThreadTest5 {
public static void main(String[] args) {
Thread t1 = new MyThread();
t1.start();
System.out.println(t1.getName()); //Thread-0
Thread t2 = new MyThread();
t2.start();
System.out.println(t2.getName()); //Thread-1
//主线程对象的名字
//哪个线程执行它,它就会得到哪个线程对象
Thread m = Thread.currentThread();
System.out.println(m.getName()); //main
for (int i = 0; i <= 5; i++) {
System.out.println("main线程输出:" + i);
}
}
}
public void setName(String name) |
另一种方法
public final void join()... |
其他方法的说明
Thread类还提供了诸如:yield、interrupt、守护线程、线程优先级等线程的控制方法,在开发中很少使用,这些方法后续需要用到的时候再深入学习。
END
学习自:黑马程序员——Java课程