• 手写FutureTask获取异步线程执行结果


    直接上代码

    package com.itbac.thread;
    
    import java.util.Iterator;
    import java.util.concurrent.Callable;
    import java.util.concurrent.LinkedBlockingQueue;
    import java.util.concurrent.locks.LockSupport;
    
    /**
     * 手写FutureTask获取异步线程执行结果
     */
    public class BacFutureTask<T> implements Runnable{
    
        Callable<T> callable;
        //任务结果
        T result;
        //任务状态: 0 初始状态,1 任务执行完成
        volatile int state = 0;
        //等待队列
        LinkedBlockingQueue<Thread> waiters = new LinkedBlockingQueue<>();
    
    
        public BacFutureTask() {
        }
    
        public BacFutureTask(Callable<T> callable) {
            this.callable = callable;
        }
    
        @Override
        public void run() {
            try {
                result = callable.call();
            } catch (Exception e) {
                e.printStackTrace();
            }finally {
                state = 1;
                //线程唤醒
                if (!waiters.isEmpty()) {
                    Iterator<Thread> iterator = waiters.iterator();
                    while (iterator.hasNext()) {
                        Thread next = iterator.next();
                        LockSupport.unpark(next);
                    }
                }
            }
        }
        //获取异步任务的结果
        public T get() {
            while (0 == state) {
                //加入等待集合
                waiters.add(Thread.currentThread());
                if (0 == state) {
                    //再次判断,为了安全。
                    // 确保当前线程一定进入等待集合后,
                    // 异步线程state = 1还没执行,才能挂起
                    LockSupport.park();
                }
                //从集合中删除
                waiters.remove(Thread.currentThread());
            }
            return result;
        }
    }

    测试:

    package com;
    
    import com.itbac.thread.BacFutureTask;
    
    import java.util.concurrent.Callable;
    
    public class BacFutureTaskTest {
        public static void main(String[] args) {
            
            BacFutureTask<String> futureTask = new BacFutureTask<>(new Callable<String>() {
                @Override
                public String call() throws Exception {
                    Thread.sleep(1000);
                    System.out.println("异步任务开始执行。");
                    //TODO 复杂的业务逻辑
                    return "异步任务结果";
                }
            });
    
            new Thread(futureTask).start();
    
            String s = futureTask.get();
    
            System.out.println(s);
    
    
        }
    }

    输出:

    异步任务开始执行。
    异步任务结果

  • 相关阅读:
    实现一个程序两套快捷键
    SystemC中文教程一
    logback的使用和logback.xml详解
    mysql语句练习50题
    Intellij IDEA中使用Debug调试详解
    用node-webkit把web应用打包成桌面应用
    Idea导入项目详解
    iReport 5.6.0 Error: net.sf.jasperreports.engine.JRException: Error executing SQL statement for : data 最优解决方案
    CentOS 7.X 关闭防火墙
    将 MySQL root 的远程访问密码由空密码改为 password
  • 原文地址:https://www.cnblogs.com/itbac/p/11923979.html
Copyright © 2020-2023  润新知