= Incredibly easy functional concurrency in Java = The purpose of Conja is to make it trivially easy for Java programmers to take advantage of multicore processors. It basically wraps {{{java.utils.concurrent}}} in syntactic sugar that encourages a functional style. It provides many of the same advantages that [http://gee.cs.oswego.edu/dl/concurrency-interest/ jsr166y] does (slated for inclusion in Java 7), though it's somewhat different under the hood. Also, Conja seems to me to be easier to use :) === What it's not === Conja is not a JVM-based functional language like [http://www.scala-lang.org/ Scala] or [http://clojure.org/ Clojure]; those are cool and all, but here we just want to make concurrent computation easy and efficient in pure Java. Also, Conja does not provide distributed computation like [http://hadoop.apache.org/ Hadoop] or [http://www.hazelcast.com/ Hazelcast]; it just exploits multiple cores on one machine, with no configuration and minimal code changes. It has some of the same goals that Grand Central Dispatch aka [http://libdispatch.macosforge.org/ libdispatch] does for C-family languages, but Conja does not depend on kernel support or native libraries. Also, where GCD and some other concurrency libraries use FIFO queues to schedule tasks, Conja can substantially reduce the memory requirements of your program through a prioritized task scheduling approach. [#Overview Overview] [#Documentation Docs] [#Download Download] [#Support Support] ---- == Overview == === Concurrent for-each === To parallelize your computation, just replace instances of for loops: {{{ Iterable someCollection = ... for(T obj : someCollection) { doSomething(obj); } }}} with the {{{Parallel.forEach()}}} construct: {{{ Iterable someCollection = ... Parallel.forEach(someCollection, new Function() { void apply(T obj) { doSomething(obj); } }); }}} As with any concurrent computation, the individual tasks should ideally have no side effects; if you follow this functional style then you don't ever need to think about thread synchronization, because the {{{Parallel}}} construct deals with it for you. If you do want to change some external state from within each task, just make sure that the updates are thread-safe (e.g. if you're adding items to a {{{Set}}}, use a {{{ConcurrentSkipListSet}}} rather than a regular {{{HashSet}}}). It's OK to reference variables from the surrounding scope, but they must of course be {{{final}}}. === Mapping through a function === The cleanest way to store an output from each call is to use {{{Parallel.map()}}}: {{{ Map results = Parallel.map(someCollection, new Function(){ V apply(T obj) { V result = doSomething(obj); return result; } }); }}} === Iterate over anything === These constructs work on {{{Iterator}}}s or {{{Iterable}}}s (e.g. any {{{Collection}}}); there's also a variant that just repeats a task a given number of times, without providing an argument. === Nested concurrent calls work fine === What if the {{{doSomething()}}} method itself performs a {{{Parallel.forEach()}}} somewhere inside it? That's no problem at all, and is in fact encouraged. Conja handles nested concurrency gracefully; the same worker threads are used on each call, so there is no proliferation of threads. Conja internally prioritizes tasks to be executed based on depth-first ordering of the entire call tree, so that subtasks contributing to an earlier high-level task always preempt later high-level tasks and their subtasks. Basically this means that it tries to finish one whole batch of tasks before starting (or continuing) on the next batch. In fact, Conja does not even ''instantiate'' tasks (e.g., by calling {{{next()}}} on the task iterator) until near their execution time. In combination these strategies help to conserve memory (or conversely, they help avoid out-of-memory errors for large computations). (See [wiki:PrinciplesOfOperation Principles of Operation] for more details.) ---- == Documentation == * [http://dev.davidsoergel.com/maven/conja/apidocs API docs] * [wiki:PrinciplesOfOperation Principles of Operation] ---- == Download == [http://maven.apache.org/ Maven] is the easiest way to make use of conja. Just add these to your pom.xml: {{{ dev.davidsoergel.com releases http://dev.davidsoergel.com/artifactory/repo false dev.davidsoergel.com snapshots http://dev.davidsoergel.com/artifactory/repo false com.davidsoergel conja 1.051 }}} If you really want just the jar, you can get it here: [http://dev.davidsoergel.com/artifactory/libs-releases/com/davidsoergel/conja/1.051/conja-1.051.jar conja-1.051.jar] (30 KB) ''May 24, 2010''. Or get the [http://dev.davidsoergel.com/hudson/job/conja/lastStableBuild/ latest stable build] from the continuous integration server. You can also [source:/ browse the source], or get the source with Mercurial: {{{ hg clone http://hg.davidsoergel.com/conja }}} The project is [http://hg.davidsoergel.com/conja on BitBucket], so please feel free to fork it there. The only external dependency is on log4j, so if you don't use Maven, you'll need to grab that manually if it's not already in your classpath. ---- == Support == * [http://dev.davidsoergel.com/trac/conja/discussion/1 Discussion Forum] * Feel free to [mailto:dev@davidsoergel.com email me] any questions or comments * For bug reports or feature requests, please feel free to [http://dev.davidsoergel.com/trac/conja/newticket create a ticket] (you'll need to [http://dev.davidsoergel.com/trac/conja/register create an account] and [http://dev.davidsoergel.com/trac/conja/login login] first). * [report:1 view active tickets]