在Java基础部分我们知道,创建线程的两种方式:
简单对比:
与Runable相比继承Thread使用简单;但由于Java是单继承,不能再继承其他类,扩展性较差
从JDK1.5开始java.util.concurrent
包下,新增了Callable接口,可以通过实现Callable接口创建线程。
与Runable接口对比
实现Runable接口需重写run方法,而实现Callable是重写Call方法
run方法无返回值、不能抛异常
call方法有返回值、可以抛异常,相当于加强版Runable接口
Callable如何使用呢?
根据已知,推到未知
已知:
- 创建线程都是通过Thread类
- Thread的构造方法不能接收Callable接口
- Thread的构造方法能接收Runable接口
未知:
于是我们就需要这样一个类,它能接收Callable接口同时实现了Runable接口
这个类就是:FutureTask
public class FutureTask<V> implements RunnableFuture<V>
public FutureTask(Callable<V> callable) {
if (callable == null)
throw new NullPointerException();
this.callable = callable;
this.state = NEW; // ensure visibility of callable
}
public class CallableDemo {
public static void main(String[] args) {
MyThread myThread = new MyThread();
FutureTask<Integer> futureTask = new FutureTask<>(myThread);
Thread t1 = new Thread(futureTask,"t1");
t1.start();
}
}
class MyThread implements Callable<Integer>{
@Override
public Integer call() throws Exception {
System.out.println("**********call**********");
return 1024;
}
}
已经有Runable(JDK1.0)接口了,为什么在JDK1.5又提供了Callable 接口?
通过上面的简单使用可以发现两处不同:
public class CallableDemo {
public static void main(String[] args) throws ExecutionException, InterruptedException {
MyThread myThread = new MyThread();
FutureTask<Integer> futureTask = new FutureTask<>(myThread);
Thread t1 = new Thread(futureTask,"t1");
t1.start();
int result1 = 100;
int result2 = futureTask.get();
System.out.println("result:"+(result1+result2));
}
}
class MyThread implements Callable<Integer>{
@Override
public Integer call() throws Exception {
System.out.println("**********call**********");
return 1024;
}
}
注意:
通过FutureTask类提供的get()方法获取返回值时,如果没有计算完成就去强求会导致阻塞,因此应放在最后
分支合并:
无需等待某些计算复杂的线程,可以继续执行其他线程,最终在某个线程中合并其他线程的结果
改进后:
public class CallableDemo {
public static void main(String[] args) throws ExecutionException, InterruptedException {
MyThread myThread = new MyThread();
FutureTask<Integer> futureTask = new FutureTask<>(myThread);
Thread t1 = new Thread(futureTask,"t1");
t1.start();
// int result2 = futureTask.get();在此处会等待t1线程计算结束,将阻塞main线程
System.out.println(Thread.currentThread().getName() + "*****");
int result1 = 100;
while (!futureTask.isDone()){
}
int result2 = futureTask.get();
System.out.println("result:"+(result1+result2));
}
}
class MyThread implements Callable<Integer>{
@Override
public Integer call() throws Exception {
System.out.println("**********call**********");
// 模拟计算过程
try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e){ e.printStackTrace(); }
return 1024;
}
}
本文地址:https://blog.csdn.net/weixin_44371151/article/details/107123794
如对本文有疑问, 点击进行留言回复!!
SpringBoot 整合 RocketMQ 实现消息生产消费(RocketMQTemplate实现)
【学习日记】(SpringBoot-part 4)新闻管理系统—添加和修改新闻功能
网友评论