• 手写Callable、FutureTask实现主线程阻塞,获取异步线程的执行结果


    1.首先我们基于原生的Callable、FutureTask实现主线程 获取子线程的执行结果

    定义MyCallable实现Callable接口

    1. import java.util.concurrent.Callable;
    2. public class MyCallable implements Callable {
    3. @Override
    4. public Integer call() throws Exception {
    5. Thread.sleep(3000);
    6. return 1;
    7. }
    8. }

    编写测试类

    1. import java.util.concurrent.ExecutionException;
    2. import java.util.concurrent.FutureTask;
    3. public class Test {
    4. public static void main(String[] args) throws ExecutionException, InterruptedException {
    5. MyCallable myCallable = new MyCallable();
    6. FutureTask futureTask = new FutureTask<>(myCallable);
    7. new Thread(futureTask).start();
    8. Object o = futureTask.get();//执行get方法 主线程阻塞
    9. System.out.println(o);
    10. }
    11. }

    运行测试,主线程阻塞3s,等子线程执行完毕后,主线程才能继续往下执行

    原理:执行futureTask.get()时,主线程进入阻塞状态,子线程执行完毕后,再唤醒主线程,主线程能拿到子线程的返回值

    2.手写代码实现以上效果

    分析上述的代码,我们这里定义三个类:

    • 自定义的Callable接口,取名MyCallable,MyCallable结构与原生Callable接口结构一致
      1. public interface MyCallable {
      2. V call() throws Exception;
      3. }
    • 定义MyCallableImpl实现MyCallable接口
      1. public class MyCallableImpl implements MyCallable{
      2. @Override
      3. public Integer call() throws Exception {
      4. //模拟耗时任务
      5. Thread.sleep(3000);
      6. return 1;
      7. }
      8. }

    • 自定义MyFutureTask,MyFutureTask要实现Runnable接口,因为new Thread()的时候要传进去
      1. public class MyFutureTask implements Runnable{
      2. private MyCallable myCallable;
      3. private V result = null;
      4. public MyFutureTask(MyCallable myCallable) {
      5. this.myCallable = myCallable;
      6. }
      7. public V get(){
      8. synchronized (this){
      9. try {
      10. //主线程执行到这里 进入阻塞状态
      11. this.wait();
      12. } catch (InterruptedException e) {
      13. e.printStackTrace();
      14. }
      15. }
      16. return result;
      17. }
      18. @Override
      19. public void run() {
      20. try {
      21. V call = myCallable.call();
      22. //拿到子线程的执行结果
      23. result = call;
      24. //子线程执行完毕 唤醒主线程
      25. synchronized (this){
      26. this.notify();
      27. }
      28. } catch (Exception e) {
      29. e.printStackTrace();
      30. }
      31. }
      32. }

      编写测试类运行

      1. public class Test {
      2. public static void main(String[] args) {
      3. MyCallableImpl myCallable = new MyCallableImpl();
      4. MyFutureTask myFutureTask = new MyFutureTask(myCallable);
      5. //开启子线程
      6. new Thread(myFutureTask).start();
      7. //调用get方法 主线程进入阻塞 当子线程任务执行完毕 主线程才被唤醒 继续往下执行
      8. Integer result = myFutureTask.get();
      9. System.out.println(result);
      10. }
      11. }

      效果同原生代码一致,主线程阻塞3s,等子线程执行完毕之后 主线程才继续往下执行

    3.我们基于LockSupport.park() 、unpark()改进一下序号2中的代码,原理同synchronized中的wait、notify一致

    在第二步中我们定义的三个类,只有MyFutureTask需要修改,代码如下

    1. import java.util.concurrent.locks.LockSupport;
    2. public class MyFutureTask implements Runnable{
    3. private MyCallable myCallable;
    4. private V result = null;
    5. //thread为主线程对象
    6. private Thread thread = null;
    7. public MyFutureTask(MyCallable myCallable) {
    8. this.myCallable = myCallable;
    9. }
    10. public V get(){
    11. //thread为主线程 因为get()方法是在主线程中执行
    12. thread = Thread.currentThread();
    13. //主线程阻塞
    14. LockSupport.park();
    15. return result;
    16. }
    17. @Override
    18. public void run() {
    19. try {
    20. V call = myCallable.call();
    21. //拿到子线程的执行结果
    22. result = call;
    23. //子线程执行完毕 唤醒主线程
    24. LockSupport.unpark(thread);
    25. } catch (Exception e) {
    26. e.printStackTrace();
    27. }
    28. }
    29. }

    测试类同序号2中一致,直接运行验证即可

  • 相关阅读:
    让孩子更快乐的学编程,一套积木就够了,长毛象AI百变编程积木套件体验
    DVWA 靶场 Open HTTP Redirect 通关解析
    cmake中的设置目标属性set_target_properties
    c 语言stdlib.h介绍
    用于图像处理的高斯滤波器 (LoG) 拉普拉斯
    【python初学者日记】Mac版在pycharm中*.py文件点击run不运行
    大公司 Or 小公司?
    【Mybatis】3 的操作类型对象
    推荐系统实践读书笔记-02利用用户行为数据
    老叶的三束玫瑰
  • 原文地址:https://blog.csdn.net/jack__love/article/details/127425395