Fork Join!
See if you can get this recursive fork-join example to work.
package com.mcnz.jfr.jmc; import java.awt.image.BufferedImage; import java.io.File; import java.util.concurrent.ForkJoinPool; import java.util.concurrent.RecursiveAction; import javax.imageio.ImageIO; public class ForkBlurRunner { public static void main(String[] args) throws Exception { String originalImageName = "C:\\_instaloader\\nasa-logo-sm.jpg"; File imageFile = new File(originalImageName); BufferedImage originalImage = ImageIO.read(imageFile); BufferedImage editedImage = ForkBlurRunner.blur(originalImage); String editedFileName = "C:\\_instaloader\\blurred-nasa-logo.jpg"; File editedFile = new File(editedFileName); ImageIO.write(editedImage, "png", editedFile); int processors = Runtime.getRuntime().availableProcessors(); System.out.println(Integer.toString(processors) + " processor(s) available."); System.out.println("Source image: " + originalImageName); System.out.println("Output image: " + editedFileName); } public static BufferedImage blur(BufferedImage image) { int w = image.getWidth(); int h = image.getHeight(); int[] originalPixels = image.getRGB(0, 0, w, h, null, 0, w); int[] editedPixels = new int[originalPixels.length]; System.out.println("Array size is " + originalPixels.length); ForkBlur fb = new ForkBlur(originalPixels, 0, originalPixels.length, editedPixels); ForkJoinPool pool = new ForkJoinPool(); long startTime = System.currentTimeMillis(); pool.invoke(fb); long endTime = System.currentTimeMillis(); System.out.println("Image blur took " + (endTime - startTime) + " ms."); BufferedImage editedImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); editedImage.setRGB(0, 0, w, h, editedPixels, 0, w); return editedImage; } } class ForkBlur extends RecursiveAction { private int[] mSource; private int mStart; private int mLength; private int[] mDestination; protected static final int SPLIT_THRESHOLD = 10000; public ForkBlur(int[] src, int start, int length, int[] dst) { mSource = src; mStart = start; mLength = length; mDestination = dst; } @Override protected void compute() { if (mLength < SPLIT_THRESHOLD) { computeNewPixelValues(); } else { int split = mLength / 2; ForkBlur firstHalf = new ForkBlur(mSource, mStart, split, mDestination); ForkBlur secondHalf = new ForkBlur(mSource, mStart + split, mLength - split, mDestination); invokeAll(firstHalf, secondHalf); } } protected void computeNewPixelValues() { for (int index = mStart; index < mStart + mLength; index++) { try { mDestination[index] = (mSource[index]+ mSource[index-50]); } catch (Exception e) { } } } }