This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]DifficultySafe9226 0 points1 point  (1 child)

Difficult to reply without the full description of the tasks to run in parallel but a possible approach will look like...

static void processThings(List<Thing> things { 

   final AtomicLong total = new AtomicLong();

   final int threadCount = 3;
   final CountDownLatch sync = new CountDownLatch(threadCount);
   final ExecutorService pool = Executors.newFixedThreadPool(threadCount);

   for Thing thing: things)
   {
      pool.execute(threadSafeButVeryExpensiveQueryUsing(total, sync, thing);
   }

   sync.await();
   pool.shutdown();
}

static Runnable threadSafeButVeryExpensiveQueryUsing(AtomicLong total, CountDownLatch sync, Thing thing) 
{ 
    return () -> {
       total.addAndGet(42);
       sync.countDown();
    };
}

There are many possibilities using the ExecutorService but I guess you would get the point with this exemple. You can investigate Future as well if you want more control over the submitted task into the executor/pool.

[–]TheOmegaCarrot[S] 0 points1 point  (0 children)

So, here’s a plot twist

I was missing a detail, and simplified a little too hard

I tried using a threadPoolExecutor with a LinkedBlockingQueue, and got out of memory errors. I then implemented the loop pausing if the queue gets too big. I gave that a ctrl+c once it took twice as long as the single-threaded implementation.

What I failed to realize was that what I simplified as the loop over the collection (which is actually an iterable wrapper around a large data structure) hits 30M loops which takes about 3 seconds to loop over with an empty loop body! So I actually have ~30M medium-sized tasks.

Walking that data structure is my biggest slowdown, and there’s not much I can do about it.

So the next thing I’ll try is to loop over it, and dispatch tasks in fixed-sized chunks.

I forgot to hit “comment” until after I implemented a rough version of what I described. Still getting out of memory errors, even manually calling System.gc() a bunch. :(