Futures version of reading ArrayBasedDirectedGraph

ArrayBasedDirectedGraph was not very clear with `apply()` method on almost 200 lines. I've cut it into submethods and rewrite it to futures instead of ExecutorUtil's parallel works.
For 2, even if you know the number of cores, there is no globally optimum number for concurrency. This needs to be profiled and then tuned. The optimum parallelism can depend on the disk type, the number of files, file size, etc.

In short, benchmarking is the only real way to determine a good default for this concurrency factor.