Java并发编程(3)- FutureTask详解与池化思想的设计和实战二

在Java并发编程领域,FutureTask可以说是一个非常强大的利器,它通过实现RunnableFuture接口间接拥有了Runnable和Future接口的相关特性,既可以用于充当线程执行的任务(Runnable),也可以用于获取线程异步执行任务后返回的结果(Future);本文将基于FutureTask实战一个高级案例:设计一款简化版的池容器,以此学习巩固池化思想. 

言归正传,在上篇文章中:Java并发编程(2)-FutureTask详解与池化思想的设计和实战一,我们已经从源码的角度结合多线程ThreadPoolExecuto,深入剖析并解读了FutureTask 的相关API,从任务的创建、到任务的执行 最后再到 线程执行完任务后异步获取执行结果;整个过程下来,想必各位看官老爷们应该收获颇丰。

而本文我们将趁热打铁,进一步介绍FutureTask在实际项目开发中的作用;总的来说,FutureTask在实际项目开发中起到的作用有两个:

(一)FutureTask执行多任务计算的场景

比如网站“程序员实战基地fightjava.com”的首页的数据是由多个功能模块组成的:轮播图、最新课程、最新博客、最新学习路线、最新资料、友情链接等模块数据;

这些模块由于具有独立性、互不相关性,因此可以开启多个FutureTask,然后交由多线程去执行,最终再统一通过get()方法获取多线程异步执行任务的结果返回给前端浏览器(这一场景在debug最新撸的课程:Java工程师核心技术-典型案例与面试实战系列二 就有重点介绍过,感兴趣的小伙伴可以前往观看学习!)

(二)在高并发场景下确保任务只被执行一次

在很多高并发的场景下,往往我们只需要某些任务被执行一次,这种情景FutureTask就能胜任(当然啦,可能还要借助像ConcurrentHashMap这样的组件辅助;而本文要介绍的便是在这一场景下FutureTask所发挥的作用!

按照惯例,我们还是先来介绍下这一场景/需求吧:假设有一个带Key的连接池,当Key存在时,则直接返回Key对应的连接对象;当Key不存在时,则创建一个 “连接”对象;

对于这样的应用场景,通常采用的方法是使用一个Map来存储Key和连接池对应的对应关系,而由于这是出于高并发的应用场景,因此稳妥的方式是采用ConcurrentHashMap,下面debug将采用N种方式对此进行实现,当然啦,最后的实现方式当然是FutureTask啦,毕竟大佬总是最后才出场的!!!

话不多说,进入代码实战环节

(1)首先出场的是传统的实现方式,即按照常规的业务逻辑、算法实现的方式:   

@Component
@Slf4j
public class MyConnectionPool {
    private ConcurrentHashMap<String,MyConnection> connMap=new ConcurrentHashMap<>();

    //获取链接
    public MyConnection getConn(final String key){
        MyConnection conn=connMap.get(key);
        if (conn!=null){
            return conn;
        }
        conn=createConn(key);
        connMap.putIfAbsent(key,conn);
        return conn;
    }
}

代码的含义应该不难理解哈,这但凡有点英语基础的闭着眼睛都能猜出来是啥意思,除非你英语是体育老师教的:

那么到底这种方式行不行呢?其实行不行并不是由你我说了算,而是得需要先经过压测哈,因为我们上面已经说了,必须要满足“高并发环境”的前提;OK,啪的一下打开JMeter.sh,然后设置QPS=1000,甚至10000 ,很快啊,如下图所示:

从上图中就可以看出,此种方式虽然最终是可以得到想要的结果,但是却产生了大量的、很有可能会被闲置的连接资源,因此这种方式不值得推荐!

(2)第二种要出场的是“synchronized”,其实现代码如下所示:   

public synchronized MyConnection getConnA(final String key){
    MyConnection conn=connMap.get(key);
    if (conn!=null){
        return conn;
    }
    conn=createConn(key);
    connMap.putIfAbsent(key,conn);
    return conn;
}

相对于第一种方式,虽然解决了安全性问题,但是却大大牺牲了性能,无法提高前端的并发量;即 synchronized这种同步方式,虽然牺牲了性能,但却没有浪费由于大量创建的连接所占用的空间资源(这其实是一种加  独占/悲观 锁的方式)

更多请见:http://www.mark-to-win.com/tutorial/51111.html

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值