Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multi-threading Java

I am trying to implement multi-threading in my Java Mandelbrot application:

This is what I have so far:

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;

public class MandelbrotSet {
   private int numberOfIterations;
   private double realMin;
   private double realMax;
   private double imaginaryMin;
   private double imaginaryMax;
   private int width;
   private int height;
   public BufferedImage image;
   public Graphics2D imageGraphics;

   public MandelbrotSet() {
      // Set the width and the height
      this.width = 600;
      this.height = 400;
      image = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR);
      imageGraphics = image.createGraphics();
                this.realMin = -2.0;
      this.realMax = 1;
      this.imaginaryMin = -1;
      this.imaginaryMax = 1;
      this.numberOfIterations = 1000;
   }

   public Complex calculateComplexNumber(int x, int y) {
      double realPart = realMin + x * (realMax - realMin) / (this.getWidth() - 1);
      double imaginaryPart = imaginaryMax - y * (imaginaryMax - imaginaryMin) / (this.getHeight() - 1);

      return new Complex(realPart, imaginaryPart);
   }

   public void calculateMandelbrotImagePoints() {
      Thread[] threads = new Thread[4];

      for (int i = 0; i < maxThreads; i++) {
         threads[i] = new Thread(new MThread(i));
         threads[i].start();
      }
   }

   class MThread implements Runnable {
      private int i;

      public MThread(int i) {
         this.i = i;
      }

      //Method uses the thread number to draw the mandelbrot in columns
      public void run() {
         for (int x = i; x < width; x += 4) {
            for (int y = 0; y < height; y++) {
               int n = 0;
               Complex c = calculateComplexNumber(x, y);
               Complex z = c;

               while ((zNumber.modulusSquared() < 4.0D) && (n < numberOfIterations)) {
                  z = z.square();
                  z.add(c);
                  n++;
               }

               if (n == numberOfIterations) {
                  imageGraphics.setColor(Color.BLACK);
               } else {
                  imageGraphics.setColor(Color.getHSBColor(n / 100.0F, 1, 1));
               }
               imageGraphics.drawLine(x,y,x,y);
            }
         }
      }
   }
}

The problem that is occurring is that when the image is drawn incorrect pixels are displayed in the image:

https://i.sstatic.net/wq2TN.png

When I check a thread with something like:

threads[i].isAlive();

the image seems to display successfully, however the image takes much longer (up to 3x as long) to render.

Two things I was wondering.

  1. Where am I going wrong?

  2. What would be the best way for drawing Mandelbrots to a BufferedImage for a large number of iterations (>1000)?

like image 255
Greg Peters Avatar asked Mar 19 '26 15:03

Greg Peters


1 Answers

Drawing is not thread-safe, so it's not possible to draw to the same {screen, image, whatever} from multiple threads. It's possible for your threads to be interrupted (i.e. it is possible for a context switch to occur) between these lines:

                  imageGraphics.setColor(Color.getHSBColor(n / 100.0F, 1, 1));
               }
               imageGraphics.drawLine(x,y,x,y);

One option would be to give each thread its own image (say, a quarter of the image as a tile) to draw on, and then to draw the images together at the end.

like image 108
Michael Chang Avatar answered Mar 21 '26 03:03

Michael Chang



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!