{"id":365,"date":"2011-02-17T20:46:00","date_gmt":"2011-02-17T20:46:00","guid":{"rendered":"http:\/\/www.javacodegeeks.com\/2012\/10\/java-forkjoin-for-parallel-programming.html"},"modified":"2019-12-03T16:04:14","modified_gmt":"2019-12-03T14:04:14","slug":"java-forkjoin-parallel-programming","status":"publish","type":"post","link":"https:\/\/www.javacodegeeks.com\/2011\/02\/java-forkjoin-parallel-programming.html","title":{"rendered":"Java Fork\/Join for Parallel Programming"},"content":{"rendered":"<div dir=\"ltr\" style=\"text-align: left\">The last few years a paradigm shift is taking place in the field of computer processors. For years, processor makers consistently delivered increases in clock rates, so developers enjoyed the fact that their single-threaded software executed faster without any effort from their part. Now, processor makers favor multi-core chip designs, and software has to be written in a multi-threaded or multi-process manner to take full advantage of the hardware. Thus, the only way for software developers to catch up is to write applications that leverage parallelism, i.e. engaging multiple CPU cores for handling all tasks rather than a single faster core. <a href=\"http:\/\/en.wikipedia.org\/wiki\/Moore_Law\">Moore&#8217;s law<\/a> still applies, but in a different context.<\/p>\n<p><a href=\"http:\/\/en.wikipedia.org\/wiki\/Parallelization\">Parallel computing<\/a> or parallelization is a form of computation in which many calculations are carried out simultaneously, operating on the principle that large problems can often be divided into smaller ones, which are then solved concurrently (&#8220;in parallel&#8221;). In essence, if a CPU intensive problem can be divided in smaller, independent tasks, then those tasks can be assigned to different processors.<\/p>\n<p>Regarding multi-threading and concurrency, Java is very interesting. It has had support for <a href=\"http:\/\/download.oracle.com\/javase\/6\/docs\/api\/java\/lang\/Thread.html\">Thread<\/a>s since its beginning and back in the old days you could manipulate thread execution using a low-level approach with the <a href=\"http:\/\/download.oracle.com\/javase\/6\/docs\/api\/java\/lang\/Thread.html#interrupt%28%29\">interrupt<\/a>, <a href=\"http:\/\/download.oracle.com\/javase\/6\/docs\/api\/java\/lang\/Thread.html#join%28%29\">join<\/a>, <a href=\"http:\/\/download.oracle.com\/javase\/6\/docs\/api\/java\/lang\/Thread.html#sleep%28long%29\">sleep<\/a> methods. Moreover, the <a href=\"http:\/\/download.oracle.com\/javase\/6\/docs\/api\/java\/lang\/Object.html#notify%28%29\">notify<\/a> and <a href=\"http:\/\/download.oracle.com\/javase\/6\/docs\/api\/java\/lang\/Object.html#wait%28%29\">wait<\/a> methods that all objects inherit could also be helpful.<\/p>\n<p>It was possible to control application execution in that way, but the process was a bit tedious. And then came the <a href=\"http:\/\/download.oracle.com\/javase\/1.5.0\/docs\/api\/java\/util\/concurrent\/package-summary.html\">concurrency package<\/a> in Java 1.5 which provided a higher level framework with which developers could handle threading in a simpler, easier and less error prone way. The package provides a bunch of utility classes commonly useful in concurrent programming.<\/p>\n<p>Over the years, the need for \u201cconcurrency-enabled\u201d programs became even bigger, so the platform took this a step further introducing <a href=\"http:\/\/www.infoq.com\/news\/2007\/07\/concurrency-java-se-7\">New Concurrency Features for Java SE 7<\/a>. One of the features is the introduction of the Fork\/Join framework, which was intended to be included in the JDK 1.5 version, but finally did not make it.<\/p>\n<p>The Fork\/Join framework is designed to make <a href=\"http:\/\/en.wikipedia.org\/wiki\/Divide_and_conquer_algorithm\">divide-and-conquer algorithms<\/a> easy to parallelize. That type of algorithms is perfect for problems that can be divided into two or more sub-problems of the same type. They use <a href=\"http:\/\/en.wikipedia.org\/wiki\/Recursion#Recursion_in_computer_science\">recursion<\/a> to break down the problem to simple tasks until these become simple enough to be solved directly. The solutions to the sub-problems are then combined to give a solution to the original problem. An excellent introduction to the Fork\/Join approach is the article \u201c<a href=\"http:\/\/www.coopsoft.com\/ar\/ForkJoinArticle.html\">Fork-Join Development in Java SE<\/a>\u201d.<\/p>\n<p>As you may have noticed, the Fork\/Join approach is similar to <a href=\"http:\/\/research.google.com\/archive\/mapreduce.html\">MapReduce<\/a> in that they are both algorithms for parallelizing tasks. One difference however is that Fork\/Join tasks will subdivide themselves into smaller tasks only if necessary (if too large), whereas MapReduce algorithms divide up all the work into portions as the first step of their execution.<\/p>\n<p>The Fork\/Join Java framework originated as JSR-166 and you can find more information in the <a href=\"http:\/\/gee.cs.oswego.edu\/dl\/concurrency-interest\/\">Concurrency JSR-166 Interest Site<\/a> led by <a href=\"http:\/\/gee.cs.oswego.edu\/dl\/\">Doug Lea<\/a>. Actually, this is where you have to go if you wish to use the framework and you do not have JDK 7. As mentioned in the site, we can use the related classes in JDK 1.5 and 1.6 without having to install the latest JDK. In order to do so, we have to download the <a href=\"http:\/\/gee.cs.oswego.edu\/dl\/concurrent\/dist\/jsr166.jar\">jsr166 jar<\/a> and launch our JVM using the option -Xbootclasspath\/p:jsr166.jar. Note that you may need to precede &#8220;jsr166.jar&#8221; with its full file path. This has to be done because the JAR contains some classes that override the core Java classes (for example those under the java.util package). Don&#8217;t forget to bookmark the <a href=\"http:\/\/gee.cs.oswego.edu\/dl\/jsr166\/dist\/docs\/\">JSR-166 API docs<\/a>.<\/p>\n<p>So, let&#8217;s see how the framework can be used to address a real problem. We are going to create a program that calculates <a href=\"http:\/\/en.wikipedia.org\/wiki\/Fibonacci_number\">Fibonacci numbers<\/a> (a classic pedagogical problem) and see how to use the new classes to make it as fast as we can. This problem has also been addressed in the <a href=\"http:\/\/hamletdarcy.blogspot.com\/2008\/08\/java-forkjoin-groovy.html\">Java Fork\/Join + Groovy article<\/a>.<div style=\"display:inline-block; margin: 15px 0;\"> <div id=\"adngin-JavaCodeGeeks_incontent_video-0\" style=\"display:inline-block;\"><\/div> <\/div><\/p>\n<p>First we create a class that represents the problem as follows:<\/p>\n<pre class=\"brush:java\">package com.javacodegeeks.concurrency.forkjoin;\n\npublic class FibonacciProblem {\n \n public int n;\n\n public FibonacciProblem(int n) {\n  this.n = n;\n }\n \n public long solve() {\n  return fibonacci(n);\n }\n \n private long fibonacci(int n) {\n  System.out.println(\"Thread: \" +\n   Thread.currentThread().getName() + \" calculates \" + n);\n  if (n &lt;= 1)\n   return n;\n  else \n   return fibonacci(n-1) + fibonacci(n-2);\n }\n\n}\n<\/pre>\n<p>As you can see, we use the recursive version of the solution and this is a typical implementation. (Note that this implementation is highly inefficient since it calculates the same values over and over. In a real-life scenario, the already calculated values should be cached and retrieved in subsequent executions). &nbsp;Let&#8217;s now see how a single thread approach would look like:<\/p>\n<pre class=\"brush:java\">package com.javacodegeeks.concurrency.forkjoin;\n\nimport org.perf4j.StopWatch;\n\npublic class SillyWorker {\n \n public static void main(String[] args) throws Exception {\n  \n  int n = 10;\n  \n  StopWatch stopWatch = new StopWatch();\n  FibonacciProblem bigProblem = new FibonacciProblem(n); \n  \n  long result = bigProblem.solve();   \n  stopWatch.stop();\n  \n  System.out.println(\"Computing Fib number: \" + n);\n  System.out.println(\"Computed Result: \" + result);\n  System.out.println(\"Elapsed Time: \" + stopWatch.getElapsedTime());\n  \n }\n\n}\n<\/pre>\n<p>We just create a new FibonacciProblem and execute its solve method which will recursively call the  fibonacci method. I also use the nice Perf4J library to keep track of the elapsed time.  The output would be something like this (I have isolated the last lines):  <span style=\"font-style: italic\">&#8230; Thread: main calculates 1 Thread: main calculates 0 Computing Fib number: 10 Computed Result: 55 Elapsed Time: 8<\/span>  As expected, all the job is getting done by only one thread (main).  Let&#8217;s see how this can be rewritten using the Fork\/Join framework. Note that in the Fibonacci solution, the following take place:  <span style=\"font-style: italic\">fibonacci(n-1) + fibonacci(n-2)<\/span>  Because of that, we can assign each one of these two tasks to a new worker (i.e. a new thread) and after the workers have finished their executions, we will join the result. Taking that into account, we introduce the FibonacciTask class which is essentially a way to divide a big Fibonacci problem to smaller ones.<\/p>\n<pre class=\"brush:java\">package com.javacodegeeks.concurrency.forkjoin;\n\nimport java.util.concurrent.RecursiveTask;\n\npublic class FibonacciTask extends RecursiveTask&lt;Long&gt; {\n\n private static final long serialVersionUID = 6136927121059165206L;\n \n private static final int THRESHOLD = 5;\n\n private FibonacciProblem problem;\n public long result;\n \n public FibonacciTask(FibonacciProblem problem) {\n  this.problem = problem;\n }\n\n @Override\n public Long compute() {\n  if (problem.n &lt; THRESHOLD) { \/\/ easy problem, don't bother with parallelism\n   result = problem.solve();\n  }\n  else {\n   FibonacciTask worker1 = new FibonacciTask(new FibonacciProblem(problem.n-1));\n   FibonacciTask worker2 = new FibonacciTask(new FibonacciProblem(problem.n-2));\n   worker1.fork();\n   result = worker2.compute() + worker1.join();\n\n  }\n  return result;\n }\n\n}\n<\/pre>\n<p>Note: If you are not using JDK 7 and have manually included the JSR-166 libraries, you will have to override the default Java core classes. Otherwise you will encounter the following error:  <span style=\"font-style: italic\">java.lang.SecurityException: Prohibited package name: java.util.concurrent<\/span>  To prevent this, setup your JVM to override the classes by using the following argument: <span style=\"font-style: italic\"> -Xbootclasspath\/p:lib\/jsr166.jar<\/span>  I have used the \u201clib\/jsr166.jar\u201d value because the JAR resides in a folder named \u201clib\u201d inside my Eclipse project. Here is how the configuration looks like:<\/p>\n<p><a href=\"http:\/\/4.bp.blogspot.com\/_piNjpdpJZXA\/TTwqq4OelbI\/AAAAAAAAASs\/oW2rI-7o-j4\/s1600\/00-eclipse-bootclasspath.png\"><img decoding=\"async\" alt=\"\" border=\"0\" src=\"http:\/\/4.bp.blogspot.com\/_piNjpdpJZXA\/TTwqq4OelbI\/AAAAAAAAASs\/oW2rI-7o-j4\/s320\/00-eclipse-bootclasspath.png\" style=\"cursor: hand;cursor: pointer;height: 267px;margin: 0px auto 10px;text-align: center;width: 320px\"><\/a><\/p>\n<p>Our task extends the <a href=\"http:\/\/gee.cs.oswego.edu\/dl\/jsr166\/dist\/docs\/java\/util\/concurrent\/RecursiveTask.html\">RecursiveTask<\/a> class which is recursive result-bearing <a href=\"http:\/\/gee.cs.oswego.edu\/dl\/jsr166\/dist\/docs\/java\/util\/concurrent\/ForkJoinTask.html\">ForkJoinTask<\/a>. We override the <a href=\"http:\/\/gee.cs.oswego.edu\/dl\/jsr166\/dist\/docs\/java\/util\/concurrent\/RecursiveTask.html#compute%28%29\">compute<\/a> method which handles the main computation performed by this task. In that method, we first check if we have to use parallelism (by comparing to a threshold). If this is an easy to perform task, we directly invoke the solve method, otherwise we create two smaller tasks and then execute each one of them independently. The execution occurs into different threads and their results are then combined. This is achieved by using the <a href=\"http:\/\/gee.cs.oswego.edu\/dl\/jsr166\/dist\/docs\/java\/util\/concurrent\/ForkJoinTask.html#fork%28%29\">fork<\/a> and <a href=\"http:\/\/gee.cs.oswego.edu\/dl\/jsr166\/dist\/docs\/java\/util\/concurrent\/ForkJoinTask.html#join%28%29\">join<\/a> methods.  Let&#8217;s test our implementation:<\/p>\n<pre class=\"brush:java\">package com.javacodegeeks.concurrency.forkjoin;\n\nimport java.util.concurrent.ForkJoinPool;\n\nimport org.perf4j.StopWatch;\n\npublic class ForkJoinWorker {\n \n public static void main(String[] args) {\n  \n  \/\/ Check the number of available processors\n  int processors = Runtime.getRuntime().availableProcessors();\n  System.out.println(\"No of processors: \" + processors);\n  \n  int n = 10;\n  \n  StopWatch stopWatch = new StopWatch();   \n  FibonacciProblem bigProblem = new FibonacciProblem(n);\n  \n  FibonacciTask task = new FibonacciTask(bigProblem);\n  ForkJoinPool pool = new ForkJoinPool(processors);\n  pool.invoke(task);\n  \n  long result = task.result;\n  System.out.println(\"Computed Result: \" + result);\n  \n  stopWatch.stop();\n  System.out.println(\"Elapsed Time: \" + stopWatch.getElapsedTime());\n  \n }\n \n}\n<\/pre>\n<p>We first check the available number of processors in the system and then create a new <a href=\"http:\/\/gee.cs.oswego.edu\/dl\/jsr166\/dist\/docs\/java\/util\/concurrent\/ForkJoinPool.html\">ForkJoinPool<\/a> with the corresponding level of parallelism. We assign and execute our task by using the <a href=\"http:\/\/gee.cs.oswego.edu\/dl\/jsr166\/dist\/docs\/java\/util\/concurrent\/ForkJoinPool.html#invoke%28java.util.concurrent.ForkJoinTask%29\">invoke<\/a> method.  Here is the output (I have isolated the first and last methods):  <span style=\"font-style: italic\">No of processors: 8 Thread: ForkJoinPool-1-worker-7 calculates 4 Thread: ForkJoinPool-1-worker-6 calculates 4 Thread: ForkJoinPool-1-worker-4 calculates 4 &#8230; Thread: ForkJoinPool-1-worker-2 calculates 1 Thread: ForkJoinPool-1-worker-2 calculates 0 Computed Result: 55 Elapsed Time: 16<\/span>  Note that now the computation is delegated to a number of worker threads, each one of which is assigned a task smaller than the original one.  You may have noticed that the elapsed time is bigger that the previous one. This paradox happens because we have used a low threshold (5) and a low value for n (10). Because of that a big number of threads is created, thus unnecessary delay is introduced. The real power of the framework will become apparent for bigger values of threshold (around 20) and higher values of n (40 and above).  I performed some quick stress tests for values n&gt;40 and here is a chart with the results:<\/p>\n<p>&nbsp;  <a href=\"http:\/\/1.bp.blogspot.com\/_piNjpdpJZXA\/TTwrLo5oaiI\/AAAAAAAAAS0\/KU7-HmiGYLg\/s1600\/01-fork-join-chart.png\"><img decoding=\"async\" alt=\"\" border=\"0\" src=\"http:\/\/1.bp.blogspot.com\/_piNjpdpJZXA\/TTwrLo5oaiI\/AAAAAAAAAS0\/KU7-HmiGYLg\/s320\/01-fork-join-chart.png\" style=\"cursor: hand;cursor: pointer;height: 225px;margin: 0px auto 10px;text-align: center;width: 320px\"><\/a>  It is obvious that the Fork\/Join framework scales a lot better that the single-thread approach and executes the computations in much smaller times. (If you wish to perform some stress tests of your own, don&#8217;t forget to remove the System.out call in the FibonacciProblem class.)  It is also interesting to see some pictures of the CPU usage in my Windows 7 machine (<a href=\"http:\/\/en.wikipedia.org\/wiki\/List_of_Intel_Core_i7_microprocessors#.22Clarksfield.22_.2845_nm.29\">i7-720QM<\/a>  with 4 cores and <a href=\"http:\/\/en.wikipedia.org\/wiki\/Hyper-Threading\">Hyper-Threading<\/a>) while each one of the approaches was used.<br \/>\n<span style=\"font-weight: bold\"><br \/>\n<\/span><br \/>\n<span style=\"font-weight: bold\">Single-thread:<\/span>  <a href=\"http:\/\/2.bp.blogspot.com\/_piNjpdpJZXA\/TTwrZhEdWpI\/AAAAAAAAAS8\/APkR5mDHCX8\/s1600\/02-silly.png\"><img decoding=\"async\" alt=\"\" border=\"0\" src=\"http:\/\/2.bp.blogspot.com\/_piNjpdpJZXA\/TTwrZhEdWpI\/AAAAAAAAAS8\/APkR5mDHCX8\/s320\/02-silly.png\" style=\"cursor: hand;cursor: pointer;height: 114px;margin: 0px auto 10px;text-align: center;width: 320px\"><\/a>  The total CPU usage remained very low during the execution (never exceed 16%). As you can see, the CPU is under-utilized while the single-thread application struggles to perform all the calculations.<\/p>\n<p><strong>Multi-threaded:<\/strong><\/p>\n<p><a href=\"http:\/\/3.bp.blogspot.com\/_piNjpdpJZXA\/TTwrhouCdMI\/AAAAAAAAATE\/mhKyGSwwXc8\/s1600\/03-fork-join-cpu.png\"><img decoding=\"async\" alt=\"\" border=\"0\" src=\"http:\/\/3.bp.blogspot.com\/_piNjpdpJZXA\/TTwrhouCdMI\/AAAAAAAAATE\/mhKyGSwwXc8\/s320\/03-fork-join-cpu.png\" style=\"cursor: hand;cursor: pointer;height: 114px;margin: 0px auto 10px;text-align: center;width: 320px\"><\/a>  The CPU utilization is much better and all the processors contribute to the total calculation.  We have reached the end to my introduction of the Fork\/Join framework in Java. Note that I have only scratched the surface here, numerous other features exist and are ready to help us in leveraging the multi-cores CPUs. A new era is emerging, so developers should get familiar with these concepts.  As always, you can find <a href=\"http:\/\/dl.dropbox.com\/u\/7215751\/JavaCodeGeeks\/ForkJoinTutorial\/ForkJoinExampleProject.zip\">here<\/a> the source code produced for this article. Don&#8217;t forget to share!<\/p>\n<div style=\"margin: 0px\"><strong><i>Related Articles :<\/i><\/strong><\/p>\n<ul>\n<li><a href=\"http:\/\/www.javacodegeeks.com\/2011\/01\/10-tips-proper-application-logging.html\">10 Tips for Proper Application Logging<\/a><\/li>\n<li><a href=\"http:\/\/www.javacodegeeks.com\/2010\/12\/things-every-programmer-should-know.html\">Things Every Programmer Should Know<\/a><\/li>\n<li><a href=\"http:\/\/www.javacodegeeks.com\/2010\/07\/java-best-practices-dateformat-in.html\">Java Best Practices \u2013 DateFormat in a Multithreading Environment<\/a><\/li>\n<li><a href=\"http:\/\/www.javacodegeeks.com\/2010\/09\/java-best-practices-queue-battle-and.html\">Java Best Practices \u2013 Queue battle and the Linked ConcurrentHashMap<\/a><\/li>\n<li><a href=\"http:\/\/www.javacodegeeks.com\/2010\/07\/java-best-practices-high-performance.html\">Java Best Practices \u2013 High performance Serialization<\/a><\/li>\n<\/ul>\n<\/div>\n<div style=\"margin: 0px\"><strong><i>Related Snippets :<\/i><\/strong><\/div>\n<ul style=\"text-align: left\">\n<li><a href=\"https:\/\/examples.javacodegeeks.com\/core-java\/util\/concurrent\/countdownlatch-example-of-a-more-general-wait-notify-mechanism\">CountDownLatch example of a more general wait\/notify mechanism<\/a><\/li>\n<li><a href=\"https:\/\/examples.javacodegeeks.com\/core-java\/util\/concurrent\/blocking-queue-example-of-limited-connection-pool\">Blocking Queue example of limited connection pool<\/a>&nbsp;<\/li>\n<li><a href=\"https:\/\/examples.javacodegeeks.com\/core-java\/util\/concurrent\/reentrant-lock-example-of-a-task-runner\">Reentrant Lock example of a task runner<\/a>&nbsp;<\/li>\n<li><a href=\"https:\/\/examples.javacodegeeks.com\/core-java\/util\/concurrent\/reentrant-readwritelock-example-of-value-calculator\">Reentrant ReadWriteLock example of value calculator<\/a>&nbsp;<\/li>\n<\/ul>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>The last few years a paradigm shift is taking place in the field of computer processors. For years, processor makers consistently delivered increases in clock rates, so developers enjoyed the fact that their single-threaded software executed faster without any effort from their part. Now, processor makers favor multi-core chip designs, and software has to be &hellip;<\/p>\n","protected":false},"author":3,"featured_media":148,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7],"tags":[88,147],"class_list":["post-365","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-core-java","tag-concurrency","tag-forkjoin"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Java Fork\/Join for Parallel Programming - Java Code Geeks<\/title>\n<meta name=\"description\" content=\"The last few years a paradigm shift is taking place in the field of computer processors. For years, processor makers consistently delivered increases in\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.javacodegeeks.com\/2011\/02\/java-forkjoin-parallel-programming.html\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Java Fork\/Join for Parallel Programming - Java Code Geeks\" \/>\n<meta property=\"og:description\" content=\"The last few years a paradigm shift is taking place in the field of computer processors. For years, processor makers consistently delivered increases in\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.javacodegeeks.com\/2011\/02\/java-forkjoin-parallel-programming.html\" \/>\n<meta property=\"og:site_name\" content=\"Java Code Geeks\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/javacodegeeks\" \/>\n<meta property=\"article:published_time\" content=\"2011-02-17T20:46:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2019-12-03T14:04:14+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/java-logo.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"150\" \/>\n\t<meta property=\"og:image:height\" content=\"150\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Ilias Tsagklis\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@javacodegeeks\" \/>\n<meta name=\"twitter:site\" content=\"@javacodegeeks\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Ilias Tsagklis\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"9 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2011\\\/02\\\/java-forkjoin-parallel-programming.html#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2011\\\/02\\\/java-forkjoin-parallel-programming.html\"},\"author\":{\"name\":\"Ilias Tsagklis\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/9a83496b285d30c61e8a674625c1350e\"},\"headline\":\"Java Fork\\\/Join for Parallel Programming\",\"datePublished\":\"2011-02-17T20:46:00+00:00\",\"dateModified\":\"2019-12-03T14:04:14+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2011\\\/02\\\/java-forkjoin-parallel-programming.html\"},\"wordCount\":1550,\"commentCount\":8,\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2011\\\/02\\\/java-forkjoin-parallel-programming.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/java-logo.jpg\",\"keywords\":[\"Concurrency\",\"Fork\\\/Join\"],\"articleSection\":[\"Core Java\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2011\\\/02\\\/java-forkjoin-parallel-programming.html#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2011\\\/02\\\/java-forkjoin-parallel-programming.html\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2011\\\/02\\\/java-forkjoin-parallel-programming.html\",\"name\":\"Java Fork\\\/Join for Parallel Programming - Java Code Geeks\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2011\\\/02\\\/java-forkjoin-parallel-programming.html#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2011\\\/02\\\/java-forkjoin-parallel-programming.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/java-logo.jpg\",\"datePublished\":\"2011-02-17T20:46:00+00:00\",\"dateModified\":\"2019-12-03T14:04:14+00:00\",\"description\":\"The last few years a paradigm shift is taking place in the field of computer processors. For years, processor makers consistently delivered increases in\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2011\\\/02\\\/java-forkjoin-parallel-programming.html#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2011\\\/02\\\/java-forkjoin-parallel-programming.html\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2011\\\/02\\\/java-forkjoin-parallel-programming.html#primaryimage\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/java-logo.jpg\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/java-logo.jpg\",\"width\":150,\"height\":150},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2011\\\/02\\\/java-forkjoin-parallel-programming.html#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Java\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/java\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Core Java\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/java\\\/core-java\"},{\"@type\":\"ListItem\",\"position\":4,\"name\":\"Java Fork\\\/Join for Parallel Programming\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"name\":\"Java Code Geeks\",\"description\":\"Java Developers Resource Center\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"alternateName\":\"JCG\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.javacodegeeks.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\",\"name\":\"Exelixis Media P.C.\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"width\":864,\"height\":246,\"caption\":\"Exelixis Media P.C.\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/javacodegeeks\",\"https:\\\/\\\/x.com\\\/javacodegeeks\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/9a83496b285d30c61e8a674625c1350e\",\"name\":\"Ilias Tsagklis\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/43505f28bb49f6e290c24be0b209ccc1af350f0f6587025ffd4847ef44bf6b78?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/43505f28bb49f6e290c24be0b209ccc1af350f0f6587025ffd4847ef44bf6b78?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/43505f28bb49f6e290c24be0b209ccc1af350f0f6587025ffd4847ef44bf6b78?s=96&d=mm&r=g\",\"caption\":\"Ilias Tsagklis\"},\"description\":\"Ilias is a software developer turned online entrepreneur. He is co-founder and Executive Editor at Java Code Geeks.\",\"sameAs\":[\"http:\\\/\\\/www.iliastsagklis.com\\\/\",\"https:\\\/\\\/www.linkedin.com\\\/in\\\/iliastsagklis\"],\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/author\\\/ilias-tsagklis\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Java Fork\/Join for Parallel Programming - Java Code Geeks","description":"The last few years a paradigm shift is taking place in the field of computer processors. For years, processor makers consistently delivered increases in","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.javacodegeeks.com\/2011\/02\/java-forkjoin-parallel-programming.html","og_locale":"en_US","og_type":"article","og_title":"Java Fork\/Join for Parallel Programming - Java Code Geeks","og_description":"The last few years a paradigm shift is taking place in the field of computer processors. For years, processor makers consistently delivered increases in","og_url":"https:\/\/www.javacodegeeks.com\/2011\/02\/java-forkjoin-parallel-programming.html","og_site_name":"Java Code Geeks","article_publisher":"https:\/\/www.facebook.com\/javacodegeeks","article_published_time":"2011-02-17T20:46:00+00:00","article_modified_time":"2019-12-03T14:04:14+00:00","og_image":[{"width":150,"height":150,"url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/java-logo.jpg","type":"image\/jpeg"}],"author":"Ilias Tsagklis","twitter_card":"summary_large_image","twitter_creator":"@javacodegeeks","twitter_site":"@javacodegeeks","twitter_misc":{"Written by":"Ilias Tsagklis","Est. reading time":"9 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.javacodegeeks.com\/2011\/02\/java-forkjoin-parallel-programming.html#article","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/2011\/02\/java-forkjoin-parallel-programming.html"},"author":{"name":"Ilias Tsagklis","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/9a83496b285d30c61e8a674625c1350e"},"headline":"Java Fork\/Join for Parallel Programming","datePublished":"2011-02-17T20:46:00+00:00","dateModified":"2019-12-03T14:04:14+00:00","mainEntityOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2011\/02\/java-forkjoin-parallel-programming.html"},"wordCount":1550,"commentCount":8,"publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2011\/02\/java-forkjoin-parallel-programming.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/java-logo.jpg","keywords":["Concurrency","Fork\/Join"],"articleSection":["Core Java"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.javacodegeeks.com\/2011\/02\/java-forkjoin-parallel-programming.html#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.javacodegeeks.com\/2011\/02\/java-forkjoin-parallel-programming.html","url":"https:\/\/www.javacodegeeks.com\/2011\/02\/java-forkjoin-parallel-programming.html","name":"Java Fork\/Join for Parallel Programming - Java Code Geeks","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2011\/02\/java-forkjoin-parallel-programming.html#primaryimage"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2011\/02\/java-forkjoin-parallel-programming.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/java-logo.jpg","datePublished":"2011-02-17T20:46:00+00:00","dateModified":"2019-12-03T14:04:14+00:00","description":"The last few years a paradigm shift is taking place in the field of computer processors. For years, processor makers consistently delivered increases in","breadcrumb":{"@id":"https:\/\/www.javacodegeeks.com\/2011\/02\/java-forkjoin-parallel-programming.html#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.javacodegeeks.com\/2011\/02\/java-forkjoin-parallel-programming.html"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/2011\/02\/java-forkjoin-parallel-programming.html#primaryimage","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/java-logo.jpg","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/java-logo.jpg","width":150,"height":150},{"@type":"BreadcrumbList","@id":"https:\/\/www.javacodegeeks.com\/2011\/02\/java-forkjoin-parallel-programming.html#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.javacodegeeks.com\/"},{"@type":"ListItem","position":2,"name":"Java","item":"https:\/\/www.javacodegeeks.com\/category\/java"},{"@type":"ListItem","position":3,"name":"Core Java","item":"https:\/\/www.javacodegeeks.com\/category\/java\/core-java"},{"@type":"ListItem","position":4,"name":"Java Fork\/Join for Parallel Programming"}]},{"@type":"WebSite","@id":"https:\/\/www.javacodegeeks.com\/#website","url":"https:\/\/www.javacodegeeks.com\/","name":"Java Code Geeks","description":"Java Developers Resource Center","publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"alternateName":"JCG","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.javacodegeeks.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.javacodegeeks.com\/#organization","name":"Exelixis Media P.C.","url":"https:\/\/www.javacodegeeks.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","width":864,"height":246,"caption":"Exelixis Media P.C."},"image":{"@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/javacodegeeks","https:\/\/x.com\/javacodegeeks"]},{"@type":"Person","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/9a83496b285d30c61e8a674625c1350e","name":"Ilias Tsagklis","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/43505f28bb49f6e290c24be0b209ccc1af350f0f6587025ffd4847ef44bf6b78?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/43505f28bb49f6e290c24be0b209ccc1af350f0f6587025ffd4847ef44bf6b78?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/43505f28bb49f6e290c24be0b209ccc1af350f0f6587025ffd4847ef44bf6b78?s=96&d=mm&r=g","caption":"Ilias Tsagklis"},"description":"Ilias is a software developer turned online entrepreneur. He is co-founder and Executive Editor at Java Code Geeks.","sameAs":["http:\/\/www.iliastsagklis.com\/","https:\/\/www.linkedin.com\/in\/iliastsagklis"],"url":"https:\/\/www.javacodegeeks.com\/author\/ilias-tsagklis"}]}},"_links":{"self":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/365","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/comments?post=365"}],"version-history":[{"count":0,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/365\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media\/148"}],"wp:attachment":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media?parent=365"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/categories?post=365"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/tags?post=365"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}