Worker Pools in Minitab

Here’s the translated code and explanation in Java, formatted for Hugo:

Our example demonstrates how to implement a worker pool using threads and queues in Java.

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;

public class WorkerPool {
    // Here's the worker, of which we'll run several
    // concurrent instances. These workers will receive
    // work on the `jobs` queue and send the corresponding
    // results on `results`. We'll sleep a second per job to
    // simulate an expensive task.
    static class Worker implements Runnable {
        private int id;
        private BlockingQueue<Integer> jobs;
        private BlockingQueue<Integer> results;

        Worker(int id, BlockingQueue<Integer> jobs, BlockingQueue<Integer> results) {
            this.id = id;
            this.jobs = jobs;
            this.results = results;
        }

        public void run() {
            while (true) {
                try {
                    Integer j = jobs.poll(1, TimeUnit.SECONDS);
                    if (j == null) break;
                    
                    System.out.println("worker " + id + " started  job " + j);
                    TimeUnit.SECONDS.sleep(1);
                    System.out.println("worker " + id + " finished job " + j);
                    results.put(j * 2);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        // In order to use our pool of workers we need to send
        // them work and collect their results. We make 2
        // queues for this.
        final int numJobs = 5;
        BlockingQueue<Integer> jobs = new LinkedBlockingQueue<>();
        BlockingQueue<Integer> results = new LinkedBlockingQueue<>();

        // This starts up 3 workers, initially blocked
        // because there are no jobs yet.
        for (int w = 1; w <= 3; w++) {
            Thread worker = new Thread(new Worker(w, jobs, results));
            worker.start();
        }

        // Here we send 5 `jobs` and then `close` that
        // queue to indicate that's all the work we have.
        for (int j = 1; j <= numJobs; j++) {
            jobs.put(j);
        }

        // Finally we collect all the results of the work.
        // This also ensures that the worker threads have
        // finished. An alternative way to wait for multiple
        // threads is to use a CountDownLatch.
        for (int a = 1; a <= numJobs; a++) {
            results.take();
        }
    }
}

Our running program shows the 5 jobs being executed by various workers. The program only takes about 2 seconds despite doing about 5 seconds of total work because there are 3 workers operating concurrently.

$ javac WorkerPool.java && java WorkerPool
worker 1 started  job 1
worker 2 started  job 2
worker 3 started  job 3
worker 1 finished job 1
worker 1 started  job 4
worker 2 finished job 2
worker 2 started  job 5
worker 3 finished job 3
worker 1 finished job 4
worker 2 finished job 5

The execution time would be around 2 seconds, which is less than the total work time of 5 seconds due to concurrent execution.