模拟实现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);
}
}
完美
模拟实现FutureTask的更多相关文章
- java并发:获取线程执行结果(Callable、Future、FutureTask)
初识Callable and Future 在编码时,我们可以通过继承Thread或是实现Runnable接口来创建线程,但是这两种方式都存在一个缺陷:在执行完任务之后无法获取执行结果.如果需要获取执 ...
- Java 多线程Future和FutureTask
Future表示一个任务的周期,并提供了相应的方法来判断是否已经完成或者取消,以及获取任务的结果和取消任务. Future接口源码: public interface Future<V> ...
- Java 并发专题 :FutureTask 实现预加载数据 在线看电子书、浏览器浏览网页等
继续并发专题~ FutureTask 有点类似Runnable,都可以通过Thread来启动,不过FutureTask可以返回执行完毕的数据,并且FutureTask的get方法支持阻塞. 由于:Fu ...
- 多线程并发执行任务,取结果归集。终极总结:Future、FutureTask、CompletionService、CompletableFuture
目录 1.Futrue 2.FutureTask 3.CompletionService 4.CompletableFuture 5.总结 ================正文分割线========= ...
- [转载] java多线程学习-java.util.concurrent详解(二)Semaphore/FutureTask/Exchanger
转载自http://janeky.iteye.com/blog/770393 ------------------------------------------------------------- ...
- 并发编程 futuretask
package com.mrbird.api.demoThread.future; import java.util.concurrent.Callable; import java.util.con ...
- 【并发编程】【JDK源码】J.U.C--组件FutureTask、ForkJoin、BlockingQueue
原文:慕课网实战·高并发探索(十三):并发容器J.U.C -- 组件FutureTask.ForkJoin.BlockingQueue FutureTask FutureTask是J.U.C中的类,是 ...
- JAVA并行异步编程,线程池+FutureTask
java 在JDK1.5中引入一个新的并发包java.util.concurrent 该包专门为java处理并发而书写. 在java中熟悉的使用多线程的方式为两种?继续Thread类,实现Runnal ...
- Future、FutureTask实现原理浅析(源码解读)
前言 最近一直在看JUC下面的一些东西,发现很多东西都是以前用过,但是真是到原理层面自己还是很欠缺. 刚好趁这段时间不太忙,回来了便一点点学习总结. 前言 最近一直在看JUC下面的一些东西,发现很多东 ...
- 012-Future、FutureTask、CompletionService 、CompletableFuture
一.概述 创建线程的两种方式,一种是直接继承Thread,另外一种就是实现Runnable接口.这两种方式都有一个缺陷就是:在执行完任务之后无法获取执行结果.如果需要获取执行结果,就必须通过共享变量或 ...
随机推荐
- bean反射比较两个bean属性值的修改明细
1.期望:将[username]从'111'改成'222';将[address]从'这是一个测试数据'改成'这是一个真实数据'; 2.导入jar <dependency> <grou ...
- getRefs is undefined html vue2项目 报错
vue2项目提示 getRefs is undefined 在div上面写了,ref,还写了v-if 然后再watch中操作了 ref 导致报错. 分析: 组件因为v-if 为 false 没有注册和 ...
- k8s使用rbd作为存储
k8s使用rbd作为存储 如果需要使用rbd作为后端存储的话,需要先安装ceph-common 1. ceph集群创建rbd 需要提前在ceph集群上创建pool,然后创建image [root@ce ...
- python重拾第十一天-RABBITMQ队列
安装python rabbitMQ module pip install pika 官网 https://pypi.python.org/pypi/pika 安装rabbit-server服务,cen ...
- Freertos学习:在Posix环境仿真FreeRTOS
--- title: rtos-freertos-在Posix环境仿真FreeRTOS date: 2020-06-11 16:22:34 categories: tags: - freertos - ...
- IgH EtherCAT主站开发案例分享——基于NXP i.MX 8M Mini
前 言 本文档主要演示NXP i.MX 8M Mini工业开发板基于IgH EtherCAT控制伺服电机. 演示板卡是创龙科技的TLIMX8-EVM工业开发板,它是基于NXP i.MX 8M M ...
- 【ClickHouse】4:clickhouse基本操作二 建库建表导数据
背景介绍: 有三台CentOS7服务器安装了ClickHouse HostName IP 安装程序 程序端口 centf8118.sharding1.db 192.168.81.18 clickhou ...
- Vue3 整理
前言 vue2基础篇链接:https://www.cnblogs.com/xiegongzi/p/15782921.html vue2组件化开发篇链接:https://www.cnblogs.com/ ...
- 浏览器中JS的执行
JS是在浏览器中运行的,浏览器为了运行JS, 必须要编译或解释JS,因为JS是高级语言,计算机不认识,必须把它编译或解释成机器语言,其次,在运行JS的过程,浏览器还要创建堆栈,因为程序是在栈中执行,执 ...
- .NET Framework 4 请求https接口
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net ...