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 用比元素数量更少的值作为参数,则该方法将会以串行方式来执行。相反(在本案例中),该方法是以并行方式来执行的。