模拟实现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 Mapmap = 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); // 服务端线程到上游处理充值业务 SetidList = 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); } } }