private static void evolve(
		final EngineParam params,
		final BufferedImage image,
		final File outputDir,
		final long generations,
		final int generationGap
	) {
		println("Starting evolution.");
		final EvolvingImagesWorker worker = EvolvingImagesWorker.of(params, image);

		final AtomicReference<Phenotype<PolygonGene, Double>> latest =
			new AtomicReference<>();

		final AtomicLong time = new AtomicLong(0);

		worker.start((current, best) -> {
			final long generation = current.generation();

			if (generation%generationGap == 0 || generation == 1) {
				final double duration = System.currentTimeMillis() - time.get();
				final double speed = generationGap/(duration/1000.0);
				time.set(System.currentTimeMillis());

				final File file = new File(
					outputDir,
					format(IMAGE_PATTERN, generation)
				);

				final Phenotype<PolygonGene, Double> pt = best.bestPhenotype();
				if (latest.get() == null || latest.get().compareTo(pt) < 0) {
					log(
						"Writing '%s': fitness=%1.4f, speed=%1.2f.",
						file, pt.fitness(), speed
					);

					latest.set(pt);
					final PolygonChromosome ch =
						(PolygonChromosome)pt.genotype().chromosome();

					writeImage(file, ch, image.getWidth(), image.getHeight());
				} else {
					log(
						"No improvement - %07d: fitness=%1.4f, speed=%1.2f.",
						generation, pt.fitness(), speed
					);
				}
			}

			if (generation >= generations) {
				worker.stop();
			}
		});

		try {
			worker.join();
		} catch (InterruptedException e) {
			Thread.currentThread().interrupt();
		}
	}
Command line version of the Evolving images example.
jenetics.example/src/main/java/io/jenetics/example/image/EvolvingImagesCmd.java