面试官问,,假设让你编写一个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<T> {
    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<String, GuardedObject> 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<String> getIds() {
        Set<String> 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 <p>
 * 多任务版保护性暂停
 * 模拟多任务充值腾讯视频VIP
 * 业务需求:
 * 1.服务端收到充值VIP账号
 * 2.服务开启线程到上游充值VIP账号(异步的)
 * 3.服务端等待充值结果
 * 4.返回结果给用户
 *
 * </p>
 */
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<String> 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);
        }
    }
}

完美

相关文章: