学习笔记:java并发编程学习之初识Concurrent

一、初识Concurrent

第一次看见concurrent的使用是在同事写的一个抽取系统代码里,当时这部分代码没有完成,有许多的问题,另一个同事接手了这部分代码的功能开发,由于他没有多线程开发的经验,所以我就一起帮着分析。最开始看到这个时很烦燥啊,因为自己接触java时间很短,连synchronized都不知道怎么用呢,突然发现有这么个复杂的东西。当时就只好开始学习吧,毕竟是使用嘛,第一目的就是了解清楚这玩意的各个类与方法都干嘛用的,然后看了看同事的代码大概也就清楚了。感觉这和大部分人一样,能用就行。

下面是一段其中的应用

public class VoiceExtractRunnable implements Runnable {
 
    @Override
    public void run() {

        // 创建线程池
        ExecutorService service = Executors.newCachedThreadPool();
        // 声明保存各任务(线程)执行结果的集合
        List<Future<VoiceExtractExpertInRuleVO>> futures = new ArrayList<Future<VoiceExtractExpertInRuleVO>>(
                rules.size());
        // 循环提交任务
        for (VoiceExtractExpertInRuleVO ruleVO : rules) {
            ruleVO.setExtractParamVO(vo);
            futures.add(service.submit(new VoiceRuleCallable(ruleVO)));
        }

        for (Future<VoiceExtractExpertInRuleVO> f : futures) {
            try {
                VoiceExtractExpertInRuleVO r = f.get();
                returnRules.add(r); // 获取任务执行完成后的返回结果
            } catch (Exception e) {
                logger.error("", e);
            }
        }
        // 所有任务都执行完毕后,关闭线程池
        service.shutdown();
    }

}

看完这个代码(省略了大部分的业务逻辑代码)就能感觉到一个优点,就是线程的执行和结果获取是可以异步的,这样对于开发来说确实是有很大的帮助。代码结构也比较清晰。

但这个时候我主要还是在能用就行的阶段,而且也并不关心concurrent里到底有多少重要的代码。最近在学习JAVA的基础知识,看到线程安全的时候Concurrent开始进入我的视野,这时我才知道它原来是这么丰富,所以才开始一点点的了解。这个过程中也一直感觉到写这些代码的工程师确实厉害,能在实践的过程中总结出这么好的代码,供广大的开发们使用。

二、主要的类

Executor :具体Runnable任务的执行者。
ExecutorService :一个线程池管理者,其实现类有多种,我会介绍一部分。我们能把Runnable,Callable提交到池中让其调度。
Semaphore :一个计数信号量
ReentrantLock :一个可重入的互斥锁定 Lock,功能类似synchronized,但要强大的多。
Future :是与Runnable,Callable进行交互的接口,比如一个线程执行结束后取返回的结果等等,还提供了cancel终止线程。
BlockingQueue :阻塞队列。
CompletionService : ExecutorService的扩展,可以获得线程执行结果的
CountDownLatch :一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。 
CyclicBarrier :一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 
Future :Future 表示异步计算的结果。
ScheduledExecutorService :一个 ExecutorService,可安排在给定的延迟后运行或定期执行的命令。

上面是一些常用类,参考这个文章,写的比较清楚:http://www.cnblogs.com/aurawing/articles/1887056.html

我个人看了代码后对下面的这些类印象比较深刻:

ConcurrentHashMap:支持并发的hashMap

AbstractQueuedSynchronizer:提供了同步锁的基础功能实现,包含独占锁和共享锁

 对于ConcurrentHashMap这个类是一种适应于并发场景下的hashMap,是建立在分离锁基础上。其内部结构可以划分为N个段,每个段都有自己的并发锁,这样写入时可以写入不同的段中,从而提高了并发的性能。

参考:http://blog.csdn.net/fw0124/article/details/43308193

AbstractQueuedSynchronizer是Concurrent包中对锁的关键抽象实现,主要是提供了一个state字段用于控制并发,通过控制state的原子状态从而保证多线程时的锁机制。这个类是抽象类,很多的场景实现需要在特定的子类中实现。

参考:

http://www.infoq.com/cn/articles/jdk1.8-abstractqueuedsynchronizer

http://www.infoq.com/cn/articles/java8-abstractqueuedsynchronizer

三、学习到的一些知识点

这几天在看源代码中也不断的在网上查找各种资料,还是学到了不少东西。

分拆锁(lock spliting)就是若原先的程序中多处逻辑都采用同一个锁,但各个逻辑之间又相互独立,就可以拆(Spliting)为使用多个锁,每个锁守护不同的逻辑。 分拆锁有时候可以被扩展,分成可大可小加锁块的集合,并且它们归属于相互独立的对象,这样的情况就是分离锁(lock striping)。(摘自《Java并发编程实践》) 对于分离锁有个更好些的解释:分拆锁有时候可以被扩展,分成若干加锁块的集合,并且它们归属于相互独立的对象,这样的情况就是分离锁。例如,ConcurrentHashMap 的实现使用了一个包含 16 个锁的数组,每一个锁都守护 HashMap 的 1/16 。假设 Hash 值均匀分布,这将会把对于锁的请求减少到约为原来的 1/16 。这项技术使得 ConcurrentHashMap 能够支持 16 个的并发 Writer 。当多处理器系统的大负荷访问需要更好的并发性时,锁的数量还可以增加。——摘自developerworks

sun.misc.Unsafe 是一个封装了很多底层操作的类,但是网上没找到太多的资料,但在Concurrent包中用的比较多,最为关键的是其提供的方法compareAndSwap之类的方法是原子的,可以不用自己加锁。看了Concurrent包中的锁主要是通过这个方法来实现的锁状态管理。 但网上也提到他可以操作内存,也难怪叫Unsafe这名,如果在java代码里随便用的话那Java不就变成和C++差不多了,呵呵。所以除了在JDK里的单元,自己写的代码中不能直接使用这个类。

volatile关键字:这个关键字是要求多线程环境下访问受volatile修改的共享数据时具有可见性。 我确实不知道怎么解释它,推荐两篇不错的文章: http://www.ibm.com/developerworks/cn/java/j-jtp06197.html http://www.cnblogs.com/dolphin0520/p/3920373.html

 四、小感慨

在看着Concurrent包里的代码时,确实对一些精秒的设计很感叹,比如锁的设计,一种抽象与实现结合的良好设计。里面的许多小细节都体现了技术的功底,反想自己为什么设计不出这样的代码。

我感觉两方面:

1、没有实际的问题要去解决

比如Concurrent这里面的代码针对并发的编程,说实话工作中遇到的不多,一般的情况用用synchronized也是可以解决的,以前在.net里也就用用lock关键字。delphi用的时候也简单。所以没有一个好的工作场景让你去解决这些问题,说实话想都想不到。

2、基础不扎实

其实看了许多代码都是些基础应用,你说流、文件、并发这些东西都是计算机里都要面对的问题,只要掌握了这些知识,其实在实际遇到问题的时候就可以用上了。否则就会当作难题用一些其他方法规避掉,反而失去了写出更好代码的机会,时间长了就变的平庸

以后还是要多多努力学习基础,这一段时间以来我觉得自己可以在编程上有更多的收获,或许我真的能写代码到50岁,至少我觉得50岁的时候还是可以跟上时代,写出优秀的代码。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏岑玉海

RavenDb学习(一)设计模式介绍

RavenDb是一个文档型的数据库,和芒果Db是一个类型的东西,但是公司选择了它,主要是因为它对事务的支持比较好,芒果Db在事务方面有问题。 下面有一个例子...

45970
来自专栏Timhbw博客

iOS面试中被面试官问到的问题答案(一)

2016-03-1016:30:14 发表评论 1,091℃热度 1.请你谈谈static和宏定义的区别。什么时候用static什么时候用宏定义。 让你声...

75180
来自专栏小樱的经验随笔

CTF---Web入门第十六题 天下武功唯快不破

天下武功唯快不破分值:10 来源: 北邮天枢战队 难度:易 参与人数:10787人 Get Flag:2264人 答题人数:3373人 解题通过率:67% ...

31460
来自专栏Python学习心得

​Python爬虫--- 1.5 爬虫实践: 获取百度贴吧内容

原文链接:https://www.fkomm.cn/article/2018/7/22/21.html

12200
来自专栏FreeBuf

一种几乎无法被检测到的Punycode钓鱼攻击,Chrome、Firefox和Opera等浏览器都中招

国内的安全专家最近发现一种新的钓鱼攻击,“几乎无法检测”,即便平时十分谨慎的用户也可能无法逃过欺骗。黑客可利用Chrome、Firefox和Opera浏览器中的...

24690
来自专栏架构师之路

58龙哥教你“如何做系统性能优化”(纯干货)

如何做系统性能优化 性能优化的目标是什么?不外乎两个: 时间性能:减小系统执行的时间 空间性能:减小系统占用的空间 一、代码优化 做代码优化前,先了解下硬件Ca...

34140
来自专栏友弟技术工作室

程序员必知必会的那些邪恶的脚本

朝圣 前言 程序员必须掌握一定的运维知识。本文通过一些邪恶,搞破坏的方式。教会你一些危险的脚本操作。 附赠 运维意识与运维规范 1.线上操作规范 ...

35370
来自专栏腾讯Bugly的专栏

Redex 初探与 Interdex:Andorid 冷启动优化

导语 早在去年10月份,facebook就发布了介绍redex的文章,这个据说可以直接对apk做处理,既提高启动性能,又可减少安装包的利器让安卓开发者们都心动不...

69260
来自专栏逸鹏说道

【.NET】UnpackMe!Shielden+DNGuard,双层变异壳 - 脱壳详解

前言:自从脱壳神器de4dot横空出世以来,我们可以看到几乎所有的.net破文中的第一部分就是不管三七二十一把程序丢进去脱壳以及反混淆。可是你真的明白de4do...

1.5K40
来自专栏架构师之路

龙神教你“如何做系统性能优化”

性能优化的目标是什么?不外乎两个: 时间性能:减小系统执行的时间 空间性能:减小系统占用的空间 一、代码优化 做代码优化前,先了解下硬件Cache: (1)C...

30570

扫码关注云+社区

领取腾讯云代金券