Null pointer error in thread

would you recommend using this example you posted a while back, I held of on implementation as I didnt understand everything, and was also focusing on gui.

/**
 * Linked Balls (v4.31)
 * (Double Buffer Remix)
 *
 * by  NatashaGunaratna (2014/Feb)
 * mod Quark & GoToLoop
 *
 * Forum.Processing.org/two/discussion/5886/multithreading-madness#Item_17
 *
 * Forum.Processing.org/two/discussion/3087/
 * how-to-draw-lines-between-my-circles-where-they-overlap#Item_3
 *
 * Studio.ProcessingTogether.com/sp/pad/export/ro.989GaZC5t7EkE
 */
 
static final int FPS = 60, DELAY = 1000/FPS >> 2;
static final int NUM = 0100, MIN = 020, MAX = 0100;
final Particle[] balls = new Particle[NUM];
 
static final String ENGINE = JAVA2D;
//static final String ENGINE = FX2D;
//static final String ENGINE = P2D;
//static final String ENGINE = P3D;
 
PGraphics mainCanvas, altCanvas;
boolean isMainCanvas, isLooping = true;
 
void setup() {
  size(800, 600, ENGINE);
  frameRate(FPS);
 
  for ( int i = 0; i != NUM; balls[i++] = new Particle(
    random(MAX>>1, width - MAX), random(MAX>>1, height>>1), 
    (int) random(MIN, MAX)) );
 
  mainCanvas = createCanvas();
  altCanvas  = createCanvas();
 
  thread("render");
}
 
void draw() {
  background(isMainCanvas? altCanvas : mainCanvas);
  frame.setTitle("FPS: " + round(frameRate));
  //surface.setTitle("FPS: " + round(frameRate));
}
 
void mousePressed() {
  if (isLooping ^= true)  loop();
  else                    noLoop();
}
 
void keyPressed() {
  mousePressed();
}
 
void render() {
  final PGraphics main = mainCanvas, alt = altCanvas;
  final Particle[] particles = balls;
 
  while (true) {
    final PGraphics pg = isMainCanvas? main : alt;
    final int fc = frameCount;
 
    pg.beginDraw();
    pg.background(-1);
 
    for (int j, i = 0; i < NUM; ) {
      pg.stroke(0);
      final Particle b = particles[j = i++].script(pg);
 
      pg.stroke(Particle.LINK);
      while (++j < NUM) {
        final Particle p = particles[j];
        if (b.isIntersecting(p))  b.linkToParticle(p, pg);
      }
    }
 
    pg.endDraw();
    isMainCanvas ^= true;
 
    if (fc == frameCount) {
      println();
 
      do {
        print(".");
        delay(DELAY);
      } while (fc == frameCount);
    }
  }
}
 
PGraphics createCanvas() {
  final PGraphics pg = createGraphics(width, height,FX2D);
 
  pg.beginDraw();
  pg.colorMode(RGB);
  pg.ellipseMode(CENTER);
  pg.smooth();
  pg.noFill();
  pg.strokeWeight(2);
  pg.endDraw();
 
  return pg;
}
 
final class Particle {
  static final color LINK = #FF4040;
  static final float GRAV = .15;
 
  float x, y;
  final short d, r;
  float sx = random(.3, 1.5), sy = random(.1, .5);
 
  Particle(final float xx, final float yy, final int dd) {
    x = xx;
    y = yy;
    d = (short) dd;
    r = (short) (dd>>1);
  }
 
  Particle script(final PGraphics pg) {
    return move().bounce().gravity().display(pg);
  }
 
  Particle move() {
    x += sx;
    y += sy;
 
    return this;
  }
 
  Particle bounce() {
    if (x > width  - r | x < r) {
      sx *= -1.;
      move();
    }
 
    if (y > height - r | y < r) {
      sy *= -1.;
      move();
    }
 
    return this;
  }
 
  Particle gravity() {
    sy += GRAV;
    return this;
  }
 
  Particle display(final PGraphics pg) {
    pg.ellipse(x, y, d, d);
    return this;
  }
 
  Particle linkToParticle(final Particle p, final PGraphics pg) {
    pg.line(x, y, p.x, p.y);
    return this;
  }
 
  boolean isIntersecting(final Particle p) {
    return sq(p.x - x) + sq(p.y - y) < sq(p.r + r);
  }
}