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);
}
}

完美

模拟实现FutureTask的更多相关文章

  1. java并发:获取线程执行结果(Callable、Future、FutureTask)

    初识Callable and Future 在编码时,我们可以通过继承Thread或是实现Runnable接口来创建线程,但是这两种方式都存在一个缺陷:在执行完任务之后无法获取执行结果.如果需要获取执 ...

  2. Java 多线程Future和FutureTask

    Future表示一个任务的周期,并提供了相应的方法来判断是否已经完成或者取消,以及获取任务的结果和取消任务. Future接口源码: public interface Future<V> ...

  3. Java 并发专题 :FutureTask 实现预加载数据 在线看电子书、浏览器浏览网页等

    继续并发专题~ FutureTask 有点类似Runnable,都可以通过Thread来启动,不过FutureTask可以返回执行完毕的数据,并且FutureTask的get方法支持阻塞. 由于:Fu ...

  4. 多线程并发执行任务,取结果归集。终极总结:Future、FutureTask、CompletionService、CompletableFuture

    目录 1.Futrue 2.FutureTask 3.CompletionService 4.CompletableFuture 5.总结 ================正文分割线========= ...

  5. [转载] java多线程学习-java.util.concurrent详解(二)Semaphore/FutureTask/Exchanger

    转载自http://janeky.iteye.com/blog/770393 ------------------------------------------------------------- ...

  6. 并发编程 futuretask

    package com.mrbird.api.demoThread.future; import java.util.concurrent.Callable; import java.util.con ...

  7. 【并发编程】【JDK源码】J.U.C--组件FutureTask、ForkJoin、BlockingQueue

    原文:慕课网实战·高并发探索(十三):并发容器J.U.C -- 组件FutureTask.ForkJoin.BlockingQueue FutureTask FutureTask是J.U.C中的类,是 ...

  8. JAVA并行异步编程,线程池+FutureTask

    java 在JDK1.5中引入一个新的并发包java.util.concurrent 该包专门为java处理并发而书写. 在java中熟悉的使用多线程的方式为两种?继续Thread类,实现Runnal ...

  9. Future、FutureTask实现原理浅析(源码解读)

    前言 最近一直在看JUC下面的一些东西,发现很多东西都是以前用过,但是真是到原理层面自己还是很欠缺. 刚好趁这段时间不太忙,回来了便一点点学习总结. 前言 最近一直在看JUC下面的一些东西,发现很多东 ...

  10. 012-Future、FutureTask、CompletionService 、CompletableFuture

    一.概述 创建线程的两种方式,一种是直接继承Thread,另外一种就是实现Runnable接口.这两种方式都有一个缺陷就是:在执行完任务之后无法获取执行结果.如果需要获取执行结果,就必须通过共享变量或 ...

随机推荐

  1. Java类加载和对象创建

    引言 Java代码需要被使用,必须要经过类加载器加载到内存中,然后对应的类才能够被创建使用,这文对类加载和对象创建和过程进行分析. 类加载 Java类通过懒加载的方式,经过了Loading.Linki ...

  2. 使用python脚本玩转古早TCAD软件(待更新)

    前言 TCAD(Technology Computer Aided Design),虽然原名中没有与半导体器件有关的词汇,但这种软件便是半导体工艺模拟及器件模拟的工具,可以说是EDA软件的一种.TCA ...

  3. typora中LaTeX公式常用指令

    # typora中LaTeX公式常用指令 以下指令只能保证在typora中完美显示,但是在其他编辑器中可能会部分不支持 \cal F.X.Y = KaTeX parse error: Expected ...

  4. 图最短路径之Dijkstra

    Dijkstra's shortest path algorithm 算法参考地址:Dijsktra's algorithm (geeksforgeeks.org) 算法的简介: 1)该算法用来计算最 ...

  5. Linux 内核:RCU机制与使用

    Linux 内核:RCU机制与使用 背景 学习Linux源码的时候,发现很多熟悉的数据结构多了__rcu后缀,因此了解了一下这些内容. 介绍 RCU(Read-Copy Update)是数据同步的一种 ...

  6. 【论文阅读】IROS2017: Voxblox & RAL2019: Voxblox++

    IROS2017: Voxblox & RAL2019: Voxblox++ Status: Finished Type: RAL Year: 2019 组织/Sensor: ETH-ASL ...

  7. Window版 MySQL可视化工具 Navicat 面安装免激活绿色版

    网盘地址 链接:https://pan.baidu.com/s/1T0WyhGAFEt28GaU4wXhfrg 提取码:z4ww navicat15破解版 链接:https://pan.baidu.c ...

  8. 推荐一款Python接口自动化测试数据提取分析神器!

    1.引言 在处理JSON数据时,我们常常需要提取.筛选或者变换数据.手动编写这些操作的代码不仅繁琐,而且容易出错.Python作为一个功能强大的编程语言,拥有丰富的库和工具来处理这些数据.今天,将介绍 ...

  9. 深入理解 React 的 useSyncExternalStore Hook

    深入理解 React 的 useSyncExternalStore Hook 大家好,今天我们来聊聊 React 18 引入的一个新 Hook:useSyncExternalStore.这个 Hook ...

  10. 2行JS代码实现Vue全选和反选

    实现效果: 第一行:子选项的选中状态 等于 全选框的状态 this.letters.forEach(item => item.check = this.checkAll) 第二行: 使用数组 e ...