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. restTemplate.getForEntity restTemplate.getForObject GET请求

    //带参数 @Test public void testGet1(){ String url = "http://IP:PORT/query?token={token}&memNo= ...

  2. linux日志查询less及堡垒机查询日志方法

    方法1tail -f orderFile.log | grep "关键字" postman接口请求的时候,关注控制台对关键字过滤的打印输出. 方法2less 文件名称/ 关键字n ...

  3. http请求方式-RestTemplate

    http请求方式-RestTemplate import com.alibaba.fastjson.JSON; import com.example.core.mydemo.http.OrderReq ...

  4. python selenium.remote远程连接时间达10分钟

    问题: 在机器A搭建了selenium-grid的环境,hub以4444端口号启动,并在4444下注册了子node,端口4445,浏览器配置chrome 使用代码进行远程连接,并创建会话: 传入的se ...

  5. Centos编译加载toa模块

    什么是toa模块 toa模块是为了让后端的realserver能够看到真实的clientip而不是lvs的dip 安装步骤 安装依赖包 yum -y install kernel-devel gcc ...

  6. HarmonyOS SDK助力中国建设银行探索金融领域创新场景

    今年年初,中国建设银行(以下简称建行)手机银行首批适配HarmonyOS NEXT,并高效实现其应用的核心功能迁移.同时,建行手机银行在HarmonyOS SDK的加持下,充分发挥鸿蒙原生应用在原生智 ...

  7. 解决keil5仿真错误:Encountered an improper argument

    --- title: 解决keil5仿真错误:Encountered an improper argument date: 2020-06-18 03:13:18 categories: tags: ...

  8. 【Playwright+Python】系列教程(四)Pytest 插件在Playwright中的使用

    一.命令行使用详解 使用Pytest插件在Playwright 中来编写端到端的测试. 1.命令行执行测试 pytest --browser webkit --headed 2.使用 pytest.i ...

  9. 痞子衡嵌入式:浅聊恩智浦i.MXRT官方SDK里关于串行Flash相关的驱动与例程资源(上篇)

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是恩智浦i.MXRT官方SDK里关于串行Flash相关的驱动与例程资源. 经常有同事以及 i.MXRT 客户咨询痞子衡,咱们恩智浦官方 S ...

  10. Nuxt框架中内置组件详解及使用指南(三)

    title: Nuxt框架中内置组件详解及使用指南(三) date: 2024/7/8 updated: 2024/7/8 author: cmdragon excerpt: 摘要:"Nux ...