Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I make a slow "for loop" faster with multithreading?

Let's say I have a very slow and big for loop.

How do I split this up in multiple threads so it runs faster?

for (int a = 0; a < 30_000_000; a++) {
    for (int b = 0; b < 30_000_000; b++) {
        for (int c = 0; c < 30_000_000; c++) {
           slowMethod();
        }
    }
}
like image 393
Bob Avatar asked Dec 24 '22 07:12

Bob


1 Answers

This is a little bit broad, but use an ExecutorService with fixed thread number will make it faster when the processor number is greater than 1 and the slowMethod is independent. If the slowMethod is I/O intensive, you can increase the thread number to get higer performance.

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Main {

    public static void main(String[] args) {
        ExecutorService service = Executors.newFixedThreadPool(
                   Runtime.getRuntime().availableProcessors() + 1);

        for (int a = 0; a < 30000000; a++) {
            for (int b = 0; b < 30000000; b++) {
                for (int c = 0; c < 30000000; c++) {
                    final int a_copy = a;
                    final int b_copy = b;
                    final int c_copy = c;
                    service.execute(() -> {
                            slowMethod(a_copy, b_copy, c_copy);
                    });
                }
            }
        }
    }

    public static void slowMethod(int a, int b, int c) {

    }
}

Update

As said in the comment, it might cause task abortion since the queue's capacity is Integer.MAX_VALUE. You can let the main thread execute slowMethod when the queue is full. To achieve this, you need create the pool mannually:

BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>();
int threads = Runtime.getRuntime().availableProcessors();
ThreadPoolExecutor executor = new ThreadPoolExecutor(threads, threads,
        0, TimeUnit.MILLISECONDS,
        queue, Executors.defaultThreadFactory(),
        new ThreadPoolExecutor.CallerRunsPolicy());
like image 188
xingbin Avatar answered Jan 09 '23 00:01

xingbin