模拟实现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<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 lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;

/**
 * @author 姿势帝-博客园
 * @address https://www.cnblogs.com/newAndHui/
 * @WeChat 851298348
 * @create 01/30 7:18
 * @description <p>
 * 多任务版保护性暂停
 * 模拟多任务充值腾讯视频VIP
 * 业务需求:
 * 1.服务端收到充值VIP账号
 * 2.服务开启线程到上游充值VIP账号(异步的)
 * 3.服务端等待充值结果
 * 4.返回结果给用户
 *
 * </p>
 */
@Slf4j
public class Test07GuardedMore {
    @Test
    public void test01() {
        // 用户线程充值
        for (int i = 0; i < 10; i++) {
            User user = new User("1838027869-" + i);
            user.setName("user-" + i);
            user.start();
        }
        // 等待下单完成
        MyThreadUtil.sleep(3);
        log.info("下单完成......");
        // 服务端线程到上游处理充值业务
        Set<String> idList = MyFutureTask.getIds();
        List<String> idListNew = new ArrayList<>();
        String str = "";
        for (String s : idList) {
            str = str + s + ",";
            idListNew.add(s);
        }
        log.info("即将发货:{}", str);
        // Iterator<String> iterator = idListNew.iterator();
        Iterator<String> iterator = idList.iterator();
        int j = 0;
        while (iterator.hasNext()) {
            String orderNo = iterator.next();
            log.info("正在发货:{}", orderNo);
            HandleRecharge recharge = new HandleRecharge(orderNo);
            recharge.setName("recharge-" + j);
            recharge.start();
            j++;
        }
        log.info("发货线程准备就绪");
        // 不让主线程结束
        MyThreadUtil.sleep(100000);
    }

    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(10000L);
            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 * 10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            String result = "充值失败";
            // 模拟充值,如果为双数则充值成功
            if (anInt % 3 != 0) {
                result = "账号:[" + object.getParam() + "]充值成功!!!!!!!";
            }
            log.info("HandleRecharge-充值结果:{}", result);
            // 设置充值结果
            object.complete(result);
        }
    }

    /**
     * ConcurrentModificationException
     * 异常演示
     */
    @Test
    public void test02() {
        List<String> list = new ArrayList<>();
        list.add("A");
        list.add("B");
        list.add("C");
        // 遍历集合
        new Thread(() -> {
            Iterator<String> iterator = list.iterator();
            while (iterator.hasNext()) {
                MyThreadUtil.sleep(2);
                String next = iterator.next();
                log.info("next=" + next);
            }
        }, "t1").start();

        // 删除集合
        new Thread(() -> {
            MyThreadUtil.sleep(1);
            list.remove("A");
        }, "t2").start();

        MyThreadUtil.sleep(3);
    }
}

 

完美

posted @ 2022-01-30 22:41  李东平|一线码农  阅读(43)  评论(0编辑  收藏  举报