模拟实现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); } }