25-结果分析
结果分析
在本节中,我们成功利用 ConcurrentHashMap
来存储由user创建的operation信息。更进一步来说,散列表以 Operation
类的user字段作为一个key,并以 Concurrent LinkedDeque
作为value,基于此来存储所有与user相关联的operation。
首先,要用10个不同线程来将随机数据填充到散列中。为达此目的,要实现一个 HashFiller
的任务。但最大的问题就是在插入一个key到散列表的时候所发生的意外:如果两个线程同时插入同一个key的时候,则将会丢失其中一个线程插入的数据,并且还会出现数据竞争的情况。为了解决该类问题,就要使用 computeIfAbsent()
方法。
该方法接收一个key和一个实现 Function
接口的lambda表达式,它们会以参数的形式进行传递。如果key已经存在,则该方法会返回与key相对应的value。否则,它会执行指定的 Function
对象,还会通过 Function
把key和value返回到 HashMap
中。在本例中,由于key不存在,所以就创建了一个新的 ConcurrentLinkedDeque
类型的实例。该方法的主要优势是其执行操作是原子性的,因此,如果其他线程尝试执行相同的操作,则它就会发生阻塞直到占用该方法的操作执行完为止。
而且,在 main()
方法中还使用了 ConcurrentHashMap
的其他方法来处理存储在散列中的信息。
forEach()
:该方法接收一个实现BiConsumer
接口的lambda表达式作为参数。而该lambda表达式的另外两个参数就是正在使用的元素的key和value。该方法的lambda表达式的作用是存储所有的元素在ConcurrentHashMap
中。forEachEntry()
:该方法与上一个相同,但其lambda表达式实现的是Consumer
接口。它接收一个存储了key和value的Entry
对象作为参数。这就是执行相同功能的另一种方式。search()
:该方法接收一个实现BiFunction
接口的lambda表达式作为参数。该lambda表达式同样也是以ConcurrentHashMap
中entry的key和value作为参数。它通过BiFunction
来返回第一个非空值。reduce()
:该方法接收两个BiFunction
接口来处理ConcurrentHashMap
的元素,并聚合为一个唯一值。这可以实现一个基于ConcurrentHashMap
元素的MapReduce
操作。第一个BiFunction
接口可以转换元素的key和value成为一个唯一值,而第二个BiFunction
接口可以聚合两个不同元素的值。
所有方法都声明第一个参数名为 parallelismThreshold
。它是执行一个元素数量(近似)的操作所需的并发量。也就是说,如果 ConcurrentHashMap
用比元素数量更少的值作为参数,则该方法将会以串行方式来执行。相反(在本案例中),该方法是以并行方式来执行的。