{"id":396,"date":"2018-05-31T12:50:14","date_gmt":"2018-05-31T00:50:14","guid":{"rendered":"https:\/\/content.ronella.xyz\/apps\/wordpress\/?p=396"},"modified":"2018-06-01T14:59:08","modified_gmt":"2018-06-01T02:59:08","slug":"concurrenthashmap-parallel-operations","status":"publish","type":"post","link":"https:\/\/www.ronella.xyz\/?p=396","title":{"rendered":"ConcurrentHashMap Parallel Operations"},"content":{"rendered":"<h4>Introduction<\/h4>\n<p>In Java 8, the <strong>forEach<\/strong>, <strong>search<\/strong> and <strong>reduce<\/strong> methods of the <strong>ConcurrentHashMap<\/strong> have parallel operation capability. Normally, it is indicated by the parameter called <strong>parallelismThreshold<\/strong>. This parameter specifies the number of elements before the execution becomes parallel. For example, if the parallelismThreshold is 10 then if the number of elements to process is below 10 then it will be processed in the current thread <em>(i.e. single thread)<\/em> otherwise it will be processed in parallel.<\/p>\n<h4>Using the forEach method<\/h4>\n<p>The forEach method has different overloads but we will just be focusing on the simplest one. The one that accepts <strong>parallelismThreshold<\/strong> and <strong>BiConsumer<\/strong> parameters. To demonstrate parallel execution in action lets start with the ConcurrentHashMap that has items less than the parallelismThreshold like the following snippet <em>(see <a href=\"#concurrent_hashmap_parallel_operation_complete_code\">the complete code<\/a> at the bottom)<\/em>:<\/p>\n<h6><strong>Snippet 1 - Elements less than parallelismThreshold<\/strong><\/h6>\n<pre><strong>ConcurrentHashMap&lt;String, Integer&gt; map<\/strong> = new ConcurrentHashMap&lt;&gt;();\r\n\r\n\/\/This will generate a stream with 1 to 9 as integer content.\r\nIntStream.range(1, 10).forEach(item -&gt; map.put(String.valueOf(item), item));\r\n\r\nlong <strong>parallelismThreshold<\/strong> = 10;\r\n\r\nBiConsumer&lt;String, Integer&gt; <strong>biConsumer<\/strong> = (key, value) -&gt; {\r\n    System.out.println(\"key: \" + key + \" value: \" + value + \" thread: \" + Thread.currentThread().getName());\r\n};\r\n\r\n<strong>map.forEach(parallelismThreshold, biConsumer);<\/strong><\/pre>\n<p>Running the above snippet will not run in parallel execution since the items in the map is less than the parallelismThreshold. But updating the variable\u00a0<strong>parallelismThreshold <\/strong>variable to 9 and run it again. We must see an output like the following output:<\/p>\n<h6>Output 1 - Updating the parallelismThreshold to 9 in snippet 1<\/h6>\n<pre>key: 1 value: 1 thread: main\r\nkey: 8 value: 8 thread: ForkJoinPool.commonPool-worker-1\r\nkey: 2 value: 2 thread: main\r\nkey: 9 value: 9 thread: ForkJoinPool.commonPool-worker-1\r\nkey: 3 value: 3 thread: main\r\nkey: 4 value: 4 thread: main\r\nkey: 5 value: 5 thread: main\r\nkey: 6 value: 6 thread: main\r\nkey: 7 value: 7 thread: main<\/pre>\n<p>Notice the <strong>ForkJoinPool.commonPool-worker<\/strong> thread which indicates that the forEach method is operating on parallel.<\/p>\n<h4>Using the search method<\/h4>\n<p>The search method is the functionality to find an item in the map with parallel support. This methods has siblings namely: <strong>searchEntries<\/strong>, <strong>searchKeys<\/strong> and <strong>searchValues <\/strong>but we will just be focusing on the search method with <strong>parallelismThreshold<\/strong> and <strong>BiFunction<\/strong> parameters. For the sample usage, see the following snippet\u00a0<em>(see <a href=\"#concurrent_hashmap_parallel_operation_complete_code\">the complete code<\/a> at the bottom)<\/em>.<\/p>\n<h6>Snippet 2 - Sample usage of search method<\/h6>\n<pre>BiFunction&lt;String, Integer, Integer&gt; <strong>biFunction<\/strong> = (key, value) -&gt; {\r\n\r\n    if (key.equals(\"9\")) {\r\n        return value; \/\/Stop searching.\r\n    }\r\n    return null; \/\/Continue searching.\r\n};\r\n\r\nSystem.out.println(\"Value: \" + <strong>map.search(parallelismThreshold, biFunction)<\/strong>);\r\n<\/pre>\n<p>We can run the previous snippet after concatenating it with snippet 1. The search will stop when the BiFunction implementation return non-null value. Otherwise, the search will continue. This is good if you have a big map.<\/p>\n<h4>Using the reduce method<\/h4>\n<p>The reduce method is the one to use if we need to accumulate something from the map items to produce a single result. This also supports parallel operation and has many siblings (<em>e.g. reduceEntries, reduceKeys, reduceValues, etc ...)<\/em>. But, we will only focus on the reduce method itself that accepts <strong>parallelismThreshold<\/strong>, <strong>transformer<\/strong> <em>(i.e. BiFunction)<\/em> and <strong>reducer<\/strong> <em>(i.e. BiFunction)<\/em>.<\/p>\n<p>The transformer parameter is the one that prepares what the reducer will work on. Like for example if the wanted to work on the values of the map from snippet 1. The transformer would be something like the following:<\/p>\n<h6>Snippet 3 - Transformer logic<\/h6>\n<pre>BiFunction&lt;String, Integer, Integer&gt; <strong>transformer<\/strong> = (key, value) -&gt; value;<\/pre>\n<p>Knowing what the transformer will give us. We can write a reducer logic what will add all the values returned by the transformer logic like the following:<\/p>\n<h6>Snippet 4 - Reducer logic<\/h6>\n<pre>BiFunction&lt;Integer, Integer, Integer&gt; <strong>reducer<\/strong> = (aggr, value) -&gt; aggr + value;\r\n<\/pre>\n<p>From the snippet above, the <strong>aggr<\/strong> parameter is a variable the accumulates the <strong>value<\/strong> argument.<\/p>\n<p>Having the transformer and the reducer ready we can invoke the reduce method like the following <em>(see <a href=\"#concurrent_hashmap_parallel_operation_complete_code\">the complete code<\/a> at the bottom)<\/em>:<\/p>\n<h6>Snippet 5 - Invoking the reduce method<\/h6>\n<pre>System.out.println(\"Total: \" + <strong>map.reduce(parallelismThreshold, transformer, reducer)<\/strong>);<\/pre>\n<h4 id=\"concurrent_hashmap_parallel_operation_complete_code\">The Complete Code<\/h4>\n<pre>package xyz.ronella.concurrency;\r\n\r\nimport java.util.concurrent.ConcurrentHashMap;\r\nimport java.util.function.BiConsumer;\r\nimport java.util.function.BiFunction;\r\nimport java.util.stream.IntStream;\r\n\r\npublic class HashMap {\r\n    public static void main(String ... args) {\r\n        ConcurrentHashMap&lt;String, Integer&gt; map = new ConcurrentHashMap&lt;&gt;();\r\n\r\n        \/\/This will generate a stream with 1 to 9 as integer content.\r\n        IntStream.range(1, 10).forEach(item -&gt; map.put(String.valueOf(item), item));\r\n\r\n        long parallelismThreshold = 9;\r\n\r\n        BiConsumer&lt;String, Integer&gt; biConsumer = (key, value) -&gt; {\r\n            System.out.println(\"key: \" + key + \" value: \" + value + \" thread: \" + Thread.currentThread().getName());\r\n        };\r\n\r\n        <strong>map.forEach(parallelismThreshold, biConsumer)<\/strong>;\r\n\r\n        BiFunction&lt;String, Integer, Integer&gt; biFunction = (key, value) -&gt; {\r\n            if (key.equals(\"9\")) {\r\n                return value; \/\/Stop searching.\r\n            }\r\n            return null; \/\/Continue searching.\r\n        };\r\n\r\n        System.out.println(\"Value: \" + <strong>map.search(parallelismThreshold, biFunction)<\/strong>);\r\n\r\n        BiFunction&lt;String, Integer, Integer&gt; transformer = (key, value) -&gt; value;\r\n\r\n        BiFunction&lt;Integer, Integer, Integer&gt; reducer = (aggr, value) -&gt; aggr + value;\r\n\r\n        System.out.println(\"Total: \" + <strong>map.reduce(parallelismThreshold, transformer, reducer)<\/strong>);\r\n    }\r\n}\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Introduction In Java 8, the forEach, search and reduce methods of the ConcurrentHashMap have parallel operation capability. Normally, it is indicated by the parameter called parallelismThreshold. This parameter specifies the number of elements before the execution becomes parallel. For example, if the parallelismThreshold is 10 then if the number of elements to process is below [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[35,33],"tags":[],"_links":{"self":[{"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=\/wp\/v2\/posts\/396"}],"collection":[{"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=396"}],"version-history":[{"count":27,"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=\/wp\/v2\/posts\/396\/revisions"}],"predecessor-version":[{"id":446,"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=\/wp\/v2\/posts\/396\/revisions\/446"}],"wp:attachment":[{"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=396"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=396"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=396"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}