Java并发学习4【面试+工作】

Java并发学习4【面试+工作】

九.fork&join

Fork/Join框架是Java7提供了的一个用于并行执行任务的框架, 是一个把大任务分割成若干个小任务,最终汇总每个小任务结果后得到大任务结果的框架。

  我们再通过Fork和Join这两个单词来理解下Fork/Join框架,Fork就是把一个大任务切分为若干子任务并行的执行,Join就是合并这些子任务的执行结果,最后得到这个大任务的结果。比如计算1+2+。。+10000,可以分割成10个子任务,每个子任务分别对1000个数进行求和,最终汇总这10个子任务的结果。Fork/Join的运行流程图如下:

  我们已经很清楚Fork/Join框架的需求了,那么我们可以思考一下,如果让我们来设计一个Fork/Join框架,该如何设计?这个思考有助于你理解Fork/Join框架的设计。

  第一步分割任务。首先我们需要有一个fork类来把大任务分割成子任务,有可能子任务还是很大,所以还需要不停的分割,直到分割出的子任务足够小。

  第二步执行任务并合并结果。分割的子任务分别放在双端队列里,然后几个启动线程分别从双端队列里获取任务执行。子任务执行完的结果都统一放在一个队列里,启动一个线程从队列里拿数据,然后合并这些数据。

Fork/Join使用两个类来完成以上两件事情:

ForkJoinTask:我们要使用ForkJoin框架,必须首先创建一个ForkJoin任务。它提供在任务中执行fork()和join()操作的机制,通常情况下我们不需要直接继承ForkJoinTask类,而只需要继承它的子类,Fork/Join框架提供了以下两个子类: RecursiveAction:用于没有返回结果的任务。 RecursiveTask :用于有返回结果的任务。 ForkJoinPool :ForkJoinTask需要通过ForkJoinPool来执行,任务分割出的子任务会添加到当前工作线程所维护的双端队列中,进入队列的头部。当一个工作线程的队列里暂时没有任务时,它会随机从其他工作线程的队列的尾部获取一个任务。

例子


十.jdk并发容器

同步容器

同步容器可以简单地理解为通过synchronized来实现同步的容器,如果有多个线程调用同步容器的方法,它们将会串行执行。

同步容器将它们的状态封装起来,并对每一个公有方法进行同步。主要包括:

  • Vector
  • Stack
  • HashTable
  • Collections.synchronized方法生成,例如: Collectinons.synchronizedList() Collections.synchronizedSet() Collections.synchronizedMap() Collections.synchronizedSortedSet() Collections.synchronizedSortedMap() 其中Vector(同步的ArrayList)和Stack(继承自Vector,先进后出)、HashTable(继承自Dictionary,实现了Map接口)是比较老的容器,Thinking in Java中明确指出,这些容器现在仍然存在于JDK中是为了向以前老版本的程序兼容,在新的程序中不应该在使用。Collections的方法时将非同步的容器包裹生成对应的同步容器。

同步容器在单线程的环境下能够保证线程安全,但是通过synchronized同步方法将访问操作串行化,导致并发环境下效率低下。而且同步容器在多线程环境下的复合操作(迭代、条件运算如没有则添加等)是非线程安全,需要客户端代码来实现加锁。

并发容器

由上面的分析我们知道,同步容器并不能保证多线程安全,而并发容器是针对多个线程并发访问而设计的,在jdk5.0引入了concurrent包,其中提供了很多并发容器,极大的提升同步容器类的性能。

ConcurrentHashMap

对应的非并发容器:HashMap 目标:代替Hashtable、synchronizedMap,支持复合操作 原理:JDK6中采用一种更加细粒度的加锁机制Segment“分段锁”,JDK8中采用CAS无锁算法

CopyOnWriteArrayList

对应的非并发容器:ArrayList 目标:代替Vector、synchronizedList 原理:利用高并发往往是读多写少的特性,对读操作不加锁,对写操作,先复制一份新的集合,在新的集合上面修改,然后将新集合赋值给旧的引用,并通过volatile 保证其可见性,当然写操作的锁是必不可少的了。

CopyOnWriteArraySet

对应的费并发容器:HashSet 目标:代替synchronizedSet 原理:基于CopyOnWriteArrayList实现,其唯一的不同是在add时调用的是CopyOnWriteArrayList的addIfAbsent方法,其遍历当前Object数组,如Object数组中已有了当前元素,则直接返回,如果没有则放入Object数组的尾部,并返回。

ConcurrentSkipListMap

对应的非并发容器:TreeMap 目标:代替synchronizedSortedMap(TreeMap) 原理:Skip list(跳表)是一种可以代替平衡树的数据结构,默认是按照Key值升序的。Skip list让已排序的数据分布在多层链表中,以0-1随机数决定一个数据的向上攀升与否,通过”空间来换取时间”的一个算法。ConcurrentSkipListMap提供了一种线程安全的并发访问的排序映射表。内部是SkipList(跳表)结构实现,在理论上能够在O(log(n))时间内完成查找、插入、删除操作。

ConcurrentSkipListSet

对应的非并发容器:TreeSet 目标:代替synchronizedSortedSet 原理:内部基于ConcurrentSkipListMap实现

ConcurrentLinkedQueue

不会阻塞的队列

对应的非并发容器:Queue 原理:基于链表实现的FIFO队列(LinkedList的并发版本)

BlockingQueue:数据共享通道

比如,线程A希望线程B发一个消息,用什么方式告知线程B比较合理的呢?用BlockingQueue最为合理。

BlockingQueue是一个接口,并非一个具体的实现。 BlockingQueue之所以适合做数据共享的通道,其关键还在于Blocking上。Blocking是阻塞的意思,当服务线程(服务线程指不断获取队列中的消息,进行处理的线程)处理完成队列中的消息后,他如何得知下一条消息何时到来呢?一种傻瓜式的方案是让这个线程按照一定的时间间隔不停的循环和监控这个队列。这是可行的一种方案,但显然造成了不必要的资源浪费,而循环周期也难以确定。而BlockingQueue很好的解决了这一个问题。它会让服务线程在队列为空是时,进行等待,当有新的消息进入队列后,自动将线程唤醒。

特点:拓展了Queue,增加了可阻塞的插入和获取等操作 原理:通过ReentrantLock实现线程安全,通过Condition实现阻塞和唤醒 实现类: LinkedBlockingQueue:基于链表实现的可阻塞的FIFO队列 ArrayBlockingQueue:基于数组实现的可阻塞的FIFO队列 PriorityBlockingQueue:按优先级排序的队列

原文发布于微信公众号 - Java帮帮(javahelp)

原文发表时间:2018-05-08

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

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏BinarySec

NETBIOS主机名编码算法

最近在看SMB协议,在自己构造数据包的时候发现了一个问题。 经过查阅资料发现NETBIOS对主机名的编码方式如下: 1.将字符补齐到16字节,不够的用空格补 ...

3968
来自专栏牛客网

知识总结:C++工程师106道面试题总结(含答案详解)

可以说个人秋招就要结束了,就等两个offer通知,然后签完搞定,这里提供一下自己复习的东西吧,我也就把这个东西给搞了一遍,然后面试基本没啥问题了,如果问的很深的...

3919
来自专栏漏斗社区

Burp Suite API学习思路(二)

在上篇工具| Burp Suite API学习思路文章中,斗哥介绍了BurpSuite扩展开发的一些准备工作与利用IHttpListener接口监听模块接收返回...

1082
来自专栏Java 源码分析

CountDownLatch 源码分析

CountDownLatch 源码分析 1. 在阅读源码时做了大量的注释,并且做了一些测试分析源码内的执行流程,由于博客篇幅有限,并且代码阅读起来没有 IDE...

3546
来自专栏向治洪

ConcurrentHashMap和HashTable的区别

hashtable是做了同步的,hashmap未考虑同步。所以hashmap在单线程情况下效率较高。hashtable在的多线程情况下,同步操作能保证程序执行...

2126
来自专栏coderhuo

arm平台根据栈进行backtrace的方法

嵌入式设备开发过程中,难免会遇到各种死机问题。这类问题的定位一直是开发人员的噩梦。 死机问题常见定位手段如下:

1651
来自专栏李蔚蓬的专栏

小结:greenDAO和LitePal的区别

1. greenDAO的version等数据库属性设置都是在对应的模型类里面完成的,以Java class的属性变量的形式存储;而LitePal是在另外的一个x...

3011
来自专栏debugeeker的专栏

《coredump问题原理探究》Linux x86版4.2节函数的逆向之顺序结构

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/xuzhina/article/detai...

621
来自专栏JavaQ

Java研发方向如何准备BAT技术面试答案(上)

最近因为忙于工作,没时间整理,本篇是下班后晚上抽空整理的,文中部分答案本来是想自己好好整理一份的,但是时间真的很紧,所以就整理了一下网络上的文章链接,挑了写的不...

3695
来自专栏后台全栈之路

图文并茂解释内存池原理

在 C 语言的动态申请内存技术中,相比起 alloc/free 系统调用,内存池(memory pool)优点很多。

8686

扫码关注云+社区

领取腾讯云代金券