FutureTask原理回顾与手写FutureTask
程序员文章站
2022-03-26 20:23:00
平时大家使用FutureTask主要有以下4个步骤:1.先创建一个Callable子类,在call方法写线程需要执行的代码2.new FutureTask()在构造函数中传递Callable子类3.将该FutureTask交给线程运行4.调用get()方法阻塞等待,一直等到获取到结果为止。public class Test implements Callable{public static void main(String[] args) throws Execu...
平时大家使用FutureTask主要有以下4个步骤:
1.先创建一个Callable子类,在call方法写线程需要执行的代码
2.new FutureTask()在构造函数中传递Callable子类
3.将该FutureTask交给线程运行
4.调用get()方法阻塞等待,一直等到获取到结果为止。
public class Test implements Callable<String>{
public static void main(String[] args) throws ExecutionException, InterruptedException {
FutureTask<String> futureTask=new FutureTask<String>(new Test());
new Thread(futureTask).start();
String result=futureTask.get();
System.out.println("返回值:"+result);
}
@Override
public String call() throws Exception {
Thread.sleep(3*1000);
System.out.println(Thread.currentThread().getName() + ":一系列操作");
return "操作完成";
}
}
三秒后输出结果:操作完成
其实FutureTask的原理无非是阻塞+唤醒,可以实现阻塞+唤醒的技术有LockSupport与wait+notify/notifyAll
既然知道了原理,也知道了阻塞+唤醒可以使用到的技术,这里我们将手写一个自己的FutureTask。
第一步,先要有自己的Callable接口
public interface MyCallable<V> {
V call() throws Exception;
}
第二步:有自己FutureTask
public class MyFutureTask<V> implements Runnable {
private MyCallable<V> myCallable;
private V result;//callable对应的返回结果
private Thread cuThread;
public MyFutureTask(MyCallable<V> myCallable){
this.myCallable=myCallable;
}
@Override
public void run() {
if(myCallable!=null){
try {
result=myCallable.call();
LockSupport.unpark(cuThread);
}catch (Exception e){
e.printStackTrace();
}
}
}
public V get(){
if(result!=null){
return result;
}
//让当前的主线程变为阻塞状态
cuThread=Thread.currentThread();
LockSupport.park();
return result;
}
}
第三步:就是写咱们的调用方法了
public class Test implements MyCallable<String>{
public static void main(String[] args) {
MyFutureTask<String> myFutureTask=new MyFutureTask(new Test());
new Thread(myFutureTask).start();
String result=myFutureTask.get();
System.out.println(result);
}
@Override
public String call() throws Exception {
Thread.sleep(3*1000);
System.out.println(Thread.currentThread().getName() + ":一系列操作");
return "操作完成";
}
}
以上就是我们手写自己的FutureTask的过程了,我们还可以使用wait+notify来实现阻塞+唤醒,只需要在MyFutureTask中定义一个锁
public class MyFutureTask<V> implements Runnable {
private MyCallable<V> myCallable;
private V result;//callable对应的返回结果
private Thread cuThread;
private Object lock = new Object();
public MyFutureTask(MyCallable<V> myCallable){
this.myCallable=myCallable;
}
@Override
public void run() {
if(myCallable!=null){
try {
result=myCallable.call();
//LockSupport.unpark(cuThread);
synchronized (lock) {
lock.notify();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
public V get(){
if(result!=null){
return result;
}
//让当前的主线程变为阻塞状态
cuThread=Thread.currentThread();
//LockSupport.park();
synchronized (lock) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return result;
}
}
本文地址:https://blog.csdn.net/weixin_41464742/article/details/107695476