1.创建并启动线程的四种方式:
1)继承Thread类创建线程
2)实现Runnable接口创建线程
3)使用Callable和Future创建线程
4)使用线程池,例如用Executor框架
2.使用Callable和Future创建线程的实现步骤:
- 1.定义一个Callable接口的实现类
- 2.创建Callable实现类对象传递给FutureTask构造器
- 3.将FutureTask对象传递给Thread构造器
- 4.Thread对象调用start方法启动线程
- 5.调用FutureTask对象的get方法获取线程运行的结果
3.需求:使用2个线程异步计算1-1000,000内之和
实现代码:
public class CallableDemo {
public static void main(String[] args) throws Exception {
//1.创建并启动线程
Callable<Integer> call1 = new CallableImpl(0, 50000);
Callable<Integer> call2 = new CallableImpl(50001, 100000);
FutureTask<Integer> f1 = new FutureTask<>(call1);
FutureTask<Integer> f2 = new FutureTask<>(call2);
new Thread(f1).start();
new Thread(f2).start();
//2.获取每一个线程的结果
int ret1 = f1.get();
int ret2 = f2.get();
int ret= ret1+ret2;
System.out.println(ret);
}
}
class CallableImpl implements Callable<Integer>{
private int min;
private int max;
public CallableImpl(int min, int max) {
this.min = min;
this.max = max;
}
@Override
public Integer call() throws Exception {
int sum = 0;
for (int i = min; i <= max; i++) {
sum+=i;
}
return sum;
}
}
4.Callable和Runnable的区别如下:
1)Callable定义的方法是call,而Runnable定义的方法是run。
2)Callable的call方法可以有返回值,而Runnable的run方法不能有返回值。
3)Callable的call方法可抛出异常,而Runnable的run方法不能抛出异常。
注意:
1.FutureTask为Runnable的实现类
2.FutureTask可以视为一个闭锁,因为只有当线程运行完才会出现结果。