com.kennycason.kumo.ParallelLayeredWordCloud Maven / Gradle / Ivy
package com.kennycason.kumo;
import com.kennycason.kumo.exception.KumoException;
import org.apache.log4j.Logger;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
/**
* A LayeredWordCloud which can process each layer in its own Thread, thus
* minimizing processing time.
*
* @author @wolfposd
*/
public class ParallelLayeredWordCloud extends LayeredWordCloud {
private static final Logger LOGGER = Logger.getLogger(ParallelLayeredWordCloud.class);
private final List> executorFutures = new ArrayList<>();
private final ExecutorService executorservice;
public ParallelLayeredWordCloud(final int layers, final Dimension dimension, final CollisionMode collisionMode) {
super(layers, dimension, collisionMode);
executorservice = Executors.newFixedThreadPool(layers);
}
/**
* constructs the wordcloud specified by layer using the given
* wordfrequencies.
* This is a non-blocking call.
*
* @param layer
* Wordcloud Layer
* @param wordFrequencies
* the WordFrequencies to use as input
*/
@Override
public void build(final int layer, final List wordFrequencies) {
final Future> completionFuture = executorservice.submit(new Runnable() {
public void run() {
LOGGER.info("Starting to build WordCloud Layer " + layer + " in new Thread");
ParallelLayeredWordCloud.super.build(layer, wordFrequencies);
}
});
executorFutures.add(completionFuture);
}
/**
* Writes the wordcloud to an imagefile.
* This is a blocking call.
*
* @param outputFileName
* some file like "test.png"
*/
@Override
public void writeToFile(final String outputFileName) {
writeToFile(outputFileName, true, true);
}
/**
* Writes the wordcloud to an imagefile.
* Terminates the executor afterwards. See
* {@link #writeToFile(String, boolean, boolean)} for a non-terminating call
*
* @param outputFileName
* some file like "test.png"
* @param blockThread
* should the current thread be blocked
*/
public void writeToFile(final String outputFileName, final boolean blockThread) {
this.writeToFile(outputFileName, blockThread, true);
}
/**
* Writes the wordcloud to an imagefile.
*
* @param outputFileName
* some file like "test.png"
* @param blockThread
* should the current thread be blocked
* @param shutdownExecutor
* should the executor be shutdown afterwards. if
* false
this PLWC can still be used to build other
* layers. if true
this will become a blocking
* Thread no matter what was specified in blockThread.
*/
public void writeToFile(final String outputFileName, final boolean blockThread, final boolean shutdownExecutor) {
if (blockThread) {
waitForFuturesToBlockCurrentThread();
}
super.writeToFile(outputFileName);
if (shutdownExecutor) {
this.shutdown();
}
}
private void waitForFuturesToBlockCurrentThread() {
// we're not shutting down the executor as this would render it
// non-functional afterwards. this way it can still be used if we
// plan on building another layer on top of the previous ones
LOGGER.info("Awaiting Termination of Executors");
for(int i = 0; i < executorFutures.size(); i++) {
final Future> future = executorFutures.get(i);
try {
// cycle through all futures, invoking get() will block
// current task until the future can return a result
LOGGER.info("Performing get on Future:" + (i + 1) + "/" + executorFutures.size());
future.get();
} catch (InterruptedException | ExecutionException e) {
throw new KumoException("Error while waiting for Future of Layer " + i, e);
}
}
executorFutures.clear();
LOGGER.info("Termination Complete, Processing to File now");
}
/**
* Signals the ExecutorService to shutdown and await Termination.
* This is a blocking call.
*/
public void shutdown() {
executorservice.shutdown();
try {
executorservice.awaitTermination(Long.MAX_VALUE, TimeUnit.MINUTES);
} catch (InterruptedException e) {
throw new KumoException("Executor awaitTermination was interrupted, consider manual termination", e);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy