模拟实现FutureTask


1.背景

面试官问,,假设让你编写一个FutureTask,你的思路是.....

2.代码

2.1.GuardedObject对象

package com.common;

/**
 * @author 姿势帝-博客园
 * @address https://www.cnblogs.com/newAndHui/
 * @WeChat 851298348
 * @create 01/30 9:13
 * @description
 */
public class GuardedObject {
    private String id;
    private String param;
    private T t;

    public GuardedObject(String id, String param) {
        this.id = id;
        this.param = param;
    }

    public String getId() {
        return id;
    }

    public String getParam() {
        return param;
    }

    /**
     * 获取执行结果
     * 这里的超时时间实现可以查看join(long millis) 的源码
     *
     * @param millis
     * @return
     */
    public T get(long millis) {
        synchronized (this) {
            long base = System.currentTimeMillis();
            long now = 0;
            while (t == null) {
                long delay = millis - now;
                if (delay <= 0) {
                    break;
                }
                try {
                    this.wait(delay);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                now = System.currentTimeMillis() - base;
            }
        }
        return t;
    }

    /**
     * 设置结果
     *
     * @param t
     */
    public void complete(T t) {
        synchronized (this) {
            this.t = t;
            // 通知其他线程
            this.notifyAll();
        }
    }
}

2.2.MyFutureTask对象

package com.common;

import java.util.Hashtable;
import java.util.Map;
import java.util.Set;

/**
 * @author 姿势帝-博客园
 * @address https://www.cnblogs.com/newAndHui/
 * @WeChat 851298348
 * @create 01/30 9:13
 * @description
 */
public class MyFutureTask {
    // 存储任务
    private static Map map = new Hashtable<>();

    /**
     * 获取一个任务
     *
     * @param id
     * @return
     */
    public static GuardedObject getGuardedObject(String id) {
        // 使用get并不好,这里可以优化额,思考一下为什么?
        return map.get(id);
    }

    /**
     * 创建一个任务
     *
     * @param id
     */
    public static GuardedObject createGuardedObject(String id, String param) {
        GuardedObject object = new GuardedObject<>(id, param);
        map.put(id, object);
        return object;
    }

    /**
     * 获取所有任务编号
     *
     * @return
     */
    public static Set getIds() {
        Set keySet = map.keySet();
        return keySet;
    }
}

2.3.Test07GuardedMore对象

package com.ldp.demo01;

import com.common.GuardedObject;
import com.common.MyFutureTask;
import com.common.MyThreadUtil;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Random;
import java.util.Set;

/**
 * @author 姿势帝-博客园
 * @address https://www.cnblogs.com/newAndHui/
 * @WeChat 851298348
 * @create 01/30 7:18
 * @description 

* 多任务版保护性暂停 * 模拟多任务充值腾讯视频VIP * 业务需求: * 1.服务端收到充值VIP账号 * 2.服务开启线程到上游充值VIP账号(异步的) * 3.服务端等待充值结果 * 4.返回结果给用户 * *

*/ public class Test07GuardedMore { @Test public void test01() { // 用户线程充值 for (int i = 0; i < 20; i++) { User user = new User("1838027869-" + i); user.setName("user-" + i); user.start(); } // 等待下单完成 MyThreadUtil.sleep(5); // 服务端线程到上游处理充值业务 Set idList = MyFutureTask.getIds(); int j = 0; for (String orderNo : idList) { HandleRecharge recharge = new HandleRecharge(orderNo); recharge.setName("recharge-" + j); recharge.start(); j++; } // 不让主线程结束 MyThreadUtil.sleep(1000); } class User extends Thread { private final Logger log = LoggerFactory.getLogger(User.class); /** * 充值账号 */ private String account; public User(String account) { this.account = account; } @Override public void run() { // 模拟一个订单号 String orderNo = "NO" + System.currentTimeMillis() + new Random().nextInt(10); // 创建充值任务 GuardedObject object = MyFutureTask.createGuardedObject(orderNo, account); // 获取充值结果 log.info("开始获取订单充值结果 orderNo={},account={}", object.getId(), account); Object result = object.get(1000L); log.info("orderNo={},account={},充值结果为:{}", object.getId(), account, result); } } /** * 处理充值 */ class HandleRecharge extends Thread { private final Logger log = LoggerFactory.getLogger(HandleRecharge.class); private String orderNo; public HandleRecharge(String orderNo) { this.orderNo = orderNo; } @Override public void run() { // 获取任务 GuardedObject object = MyFutureTask.getGuardedObject(orderNo); int anInt = new Random().nextInt(10); // 模拟耗时 try { Thread.sleep(anInt * 1000); } catch (InterruptedException e) { e.printStackTrace(); } String result = "充值失败"; // 模拟充值,如果为双数则充值成功 if (anInt % 2 == 0) { result = "账号:[" + object.getParam() + "]充值成功!!!!!!!"; } log.info("HandleRecharge-充值结果:{}", result); // 设置充值结果 object.complete(result); } } }

完美