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. Spring事务隔离级别和传播机制

    引言 什么是事务? 在理解事务之前,我们要先了解事务的基本作用 比如在生活中有这样一个场景----取钱,每个人应该都干过的事 在ATM机上取钱,1.输入密码----2.输入金额----3.银行扣钱-- ...

  2. mybatis sqlmap sql in 查询

    <select id="selectBlogs" parameterType="map"> SELECT * FROM blog WHERE use ...

  3. Task2 -- 关于Lecture3

    Smiling & Weeping ---- 玲珑骰子安红豆, 入骨相思知不知. 1. 学习Git分支管理: Git分支是灵活开发的关键.创建.切换和合并分支是基础操作.使用如下命令: bas ...

  4. 12-CSS浮动

    01 介绍 02 浮动规则 03 案例练习 3.1 缝隙的解决方案 <!DOCTYPE html> <html lang="en"> <head> ...

  5. python重拾第七天-面向对象进阶

    本节内容: 面向对象高级语法部分 经典类vs新式类 静态方法.类方法.属性方法 类的特殊方法 反射 异常处理 Socket开发基础 作业:开发一个支持多用户在线的FTP程序 面向对象高级语法部分 经典 ...

  6. Android Verified Boot介绍与有关使用

    Android Verified Boot介绍与有关使用 背景 在搞安卓驱动调试的时候,由于不熟悉,导致系统没有按照我预期启动完毕:因此需要注意这一块的东西. 简介 Verified Boot 是 A ...

  7. FFmpeg开发笔记(三十五)Windows环境给FFmpeg集成libsrt

    ​<FFmpeg开发实战:从零基础到短视频上线>一书的"10.2  FFmpeg推流和拉流"提到直播行业存在RTSP和RTMP两种常见的流媒体协议.除此以外,还有比较两 ...

  8. VulnHub_DC-4渗透流程

    VulnHub_DC-4 DC-4 is another purposely built vulnerable lab with the intent of gaining experience in ...

  9. PS工具的基本使用

    常见的图片格式: 切片工具的使用 1.用切片选中图片 2.导出切片 3.切片悬着工具 可以选择指定 切片框 删除. 点击图层 切图 清除切片 基于参考线的切片 切图插件Cutterman

  10. @ConfigurationProperties 还能这样用

    在编写项目代码时,我们要求更灵活的配置,更好的模块化整合.在 Spring Boot 项目中,为满足以上要求,我们将大量的参数配置在 application.properties 或 applicat ...