Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package test;
- /*
- * A simple example of how to invert/modify bitmaps with java.
- *
- * Copyright (C) 2012 Ma_Sys.ma
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- // Basic Imports that could be helpful
- import javax.imageio.*;
- import java.awt.*;
- import java.awt.image.*;
- import java.io.*;
- import java.lang.*;
- import java.lang.reflect.*;
- import java.util.*;
- public class InvertColors {
- public static class LoopInverter extends DistributedLoopThread {
- private BufferedImage img;
- public LoopInverter(Integer start, Integer end, DistributedLoop ownerLoop) {
- super(start, end, ownerLoop);
- }
- public void pass(Object...data) {
- img = (BufferedImage)data[0];
- }
- protected void execLoop() {
- int width = img.getWidth();
- int j;
- int[] line;
- for(int i = START; i < END; i++) {
- // Get a single line of pixels
- line = img.getRGB(0, i, img.getWidth(), 1, null, 0, width);
- for(j = 0; j < line.length; j++) {
- // Actual inversion
- line[j] = 0xffffff ^ line[j];
- }
- // Store the pixels back into the image
- img.setRGB(0, i, width, 1, line, 0, width);
- }
- }
- }
- public static void main(String[] args) {
- System.out.println("Invert Colors 1.0, Copyright (c) 2012 Ma_Sys.ma.");
- System.out.println("For further info send an e-mail to Ma_Sys.ma@web.de.");
- System.out.println();
- if(args.length != 1) {
- System.out.println("Usage: java test.InvertColors [image]");
- System.exit(1);
- }
- int extensionPosition = args[0].lastIndexOf('.');
- if(extensionPosition == -1) {
- System.out.println("Unable to determine input filetype.");
- System.exit(1);
- }
- // Read image data
- BufferedImage img;
- try {
- img = ImageIO.read(new File(args[0]));
- } catch(IOException ex) {
- System.err.println("Unable to read image from " + args[0]);
- ex.printStackTrace();
- System.exit(2);
- return; // "Variable might not have been initialized."
- }
- long start = System.currentTimeMillis(); // Measure time
- // Invert all pixels using all processors
- // See LoopInverter for the actual calculation
- DistributedLoop loop;
- try {
- loop = new DistributedLoop(DistributedLoop.AUTO_DETERMINE_THREADS, 0, img.getHeight(), LoopInverter.class, null, null);
- } catch(InstantiationException ex) {
- System.err.println("Unable to create distributed loop.");
- ex.printStackTrace();
- System.exit(4);
- return; // s. o.
- }
- loop.passArgumentsOnAll(img);
- loop.startAll();
- System.out.println("Took " + (System.currentTimeMillis() - start) + " ms for the actual calculation.");
- // Write image data
- try {
- ImageIO.write(img, "png", new File(args[0].substring(0, extensionPosition) + "_inverted.png"));
- } catch(IOException ex) {
- System.err.println("Unable to write PNG image file.");
- ex.printStackTrace();
- System.exit(3);
- }
- }
- }
- // ---------------------------------------
- // From the Tools Library in Version 2.0
- // ---------------------------------------
- /**
- * <p>
- * Ermöglicht es, Rechenlast auf mehrere Kerne zu verteilen, indem eine
- * Schleife in mehrere Teile aufgesplittet wird. Somit lassen sich Schleifen
- * mit mehr Einträgen als Kerne vorhanden sind problemlos parallelisieren, wenn
- * innerhalb der Schleife kein Ergebnis des vorherigen Durchganges benötigt wird.
- * </p><p>
- * Die Nutzung ist alles andere als einfach und soll deshalb am Beispiel gezeigt
- * werden.
- * </p><p>
- * Alle Werte eines Arrays sollen initialisiert werden, indem
- * komplexe Objekte erzeugt werden, deren Erstellung lange dauert:
- * <br />
- * <pre>
- package ma.tools.concurrent;
- import ma.tools.concurrent.DistributedLoop;
- import ma.tools.concurrent.DistributedLoopThread;
- public class DistributedLoopExample {
- private static int nr = 1;
- public DistributedLoopExample() {
- super();
- int objects = 32;
- long start;
- // 1. Test mit normaler Schleife
- start = System.currentTimeMillis();
- ComplexObject[] allObjects = new ComplexObject[objects];
- for(int i = 0; i < objects; i++) {
- allObjects[i] = new ComplexObject();
- }
- System.out.println("Normalerweise braucht man " + (System.currentTimeMillis() - start) + " ms zum Erstellen der Objekte.");
- // 2. Test mit verteilter Schleife
- start = System.currentTimeMillis();
- allObjects = new ComplexObject[objects];
- DistributedLoop loop;
- try {
- loop = new DistributedLoop(DistributedLoop.AUTO_DETERMINE_THREADS, 0, objects, CreatorInstance.class, null, this);
- } catch(InstantiationException ex) {
- ex.printStackTrace();
- return;
- }
- // Wir wollen das Array nicht als mehrere Argumente übergeben
- loop.passArgumentsOnAll((Object)allObjects);
- loop.startAll();
- System.out.println("Verteilt dauert es (nur?) " + (System.currentTimeMillis() - start) + " ms");
- }
- public class CreatorInstance extends DistributedLoopThread {
- private ComplexObject[] allObjects;
- public CreatorInstance(Integer start, Integer end, DistributedLoop ownerLoop) {
- super(start, end, ownerLoop);
- }
- protected void pass(Object...data) {
- allObjects = (ComplexObject[])data[0];
- }
- protected void execLoop() {
- for(int i = START; i < END; i++) {
- allObjects[i] = new ComplexObject();
- }
- }
- }
- private class ComplexObject {
- public ComplexObject() {
- int cnr = nr++;
- System.out.println("Komplexes Objekt " + cnr + " erstellen...");
- // Zeit die es braucht um ein Objekt zu erstellen (hier künstlich verlangsamt)
- try {
- Thread.sleep(250);
- } catch(InterruptedException ex) {
- System.out.println("Komplexes Objekt " + cnr + ": Erstellung abgebrochen: " + ex.toString());
- }
- System.out.println("Komplexes Objekt " + cnr + " fertig.");
- }
- }
- public static void main(String[] args) {
- new DistributedLoopExample();
- }
- }
- * </pre>
- * <br />
- * Wenn man die "künstlich verlängernden" Zeilen wegnimmt, sieht man
- * sehr gut, dass es einen Overhead (auf dem Testsystem rund 3ms) durch
- * die Paralelisierung gibt. Deshalb lohnt es sich nur bei der Erstellung
- * von Objekten, die zusammen "relativ lange" brauchen, was auch schon bei
- * z.B. 200 ms der Fall ist. Dadurch lohnt sich das Verteilte Rechnen an
- * vielen Stellen.
- * </p>
- * <p>
- * Hinweis #1: Bei Spiecherintensiven Anwendungen könnte es anders sein.
- * Hier hilft es, beides zu testen.
- * Das ist sehr einfach möglich, indem man dem Constructor als
- * "preferredThreadCount" die Zahl 1 (keine parallelisierung)
- * übergibt. Dies vermindert den Overhead aber nur sehr geringfügig.
- * Wenn es knapp ist, sollte man eine "richtige" Schleife testen.
- * </p><p>
- * Hinweis #2: Rechenintensive Anwendungen profitieren eventuell vom
- * Java Native Interface.
- * </p><p>
- * Hinweis #3: Optimieren Sie auch den Inhalt der Schleifen
- * Sollte eigentlich klar sein.
- * </p>
- *
- * @version 1.0.1
- * @author Linux-Fan, Ma_Sys.ma
- */
- class DistributedLoop {
- public static final int AUTO_DETERMINE_THREADS = -1;
- private DistributedLoopThread[] allThreads;
- private int readyThreads;
- private boolean started;
- private DistributedLoopUser owner;
- private ArrayList<Exception> theExceptions;
- public DistributedLoop(int preferredThreadCount, int lStart, int lEnd, Class<? extends DistributedLoopThread> threadClass, DistributedLoopUser owner, Object enclosing) throws InstantiationException {
- super();
- this.owner = owner;
- theExceptions = new ArrayList<Exception>();
- int realThreadCount = 0;
- if(preferredThreadCount == AUTO_DETERMINE_THREADS) {
- realThreadCount = Runtime.getRuntime().availableProcessors();
- } else {
- realThreadCount = preferredThreadCount;
- }
- int range = lEnd - lStart;
- if(range < realThreadCount) {
- realThreadCount = range;
- }
- allThreads = new DistributedLoopThread[realThreadCount];
- readyThreads = 0;
- started = false;
- int perThread = range / allThreads.length;
- for(int i = 0; i < allThreads.length; i++) {
- final int cStart = lStart + perThread * i;
- final int cEnd;
- if(i == (allThreads.length - 1)) {
- cEnd = lEnd;
- } else {
- cEnd = lStart + perThread * (i + 1);
- }
- try {
- if(enclosing == null) {
- allThreads[i] = threadClass.getConstructor(Integer.class, Integer.class, getClass()).newInstance(cStart, cEnd, this);
- } else {
- allThreads[i] = threadClass.getConstructor(enclosing.getClass(), Integer.class, Integer.class, getClass()).newInstance(enclosing, cStart, cEnd, this);
- }
- allThreads[i].setName("Distributed Loop Thread " + (i + 1));
- } catch(Exception ex) {
- InstantiationException er = new InstantiationException("Unable to create distributed loop thread.");
- er.initCause(ex);
- throw er;
- }
- }
- }
- public Iterator<Exception> startAll() {
- if(!started) {
- started = true;
- for(int i = 0; i < allThreads.length; i++) {
- allThreads[i].start();
- }
- if(owner == null) {
- for(int i = 0; i < allThreads.length; i++) {
- try {
- allThreads[i].join();
- } catch(InterruptedException ex) {
- System.err.println("ma.tools.concurrent.DistributedLoop: Thread interrupted: " + ex.toString());
- } catch(IllegalThreadStateException ex) {
- System.err.println("ma.tools.concurrent.DistributedLoop: " + ex.toString());
- }
- }
- return theExceptions.iterator();
- } else {
- return null;
- }
- } else {
- throw new IllegalThreadStateException("Distributed loop was already started.");
- }
- }
- public void interruptAll() {
- for(int i = 0; i < allThreads.length; i++) {
- if(allThreads[i].isAlive()) {
- allThreads[i].interrupt();
- }
- }
- }
- public Object[] callOnAll(Method m, Object...params) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
- Object[] allRets = new Object[allThreads.length];
- for(int i = 0; i < allThreads.length; i++) {
- allRets[i] = m.invoke(allThreads[i], params);
- }
- return allRets;
- }
- public DistributedLoopThread[] getThreads() {
- return allThreads;
- }
- public void passArgumentsOnAll(Object...data) {
- for(int i = 0; i < allThreads.length; i++) {
- allThreads[i].pass(data);
- }
- }
- protected void readyCountUp() {
- readyThreads++;
- if(readyThreads == allThreads.length && owner != null) {
- owner.distributedThreadsReady(theExceptions.toArray(new Exception[theExceptions.size()]));
- }
- }
- protected void passException(Exception ex) {
- theExceptions.add(ex);
- }
- public Iterator<Exception> getExceptions() {
- return theExceptions.iterator();
- }
- }
- abstract class DistributedLoopThread extends Thread {
- protected final int START;
- protected final int END;
- protected final DistributedLoop OWNER;
- public DistributedLoopThread(Integer start, Integer end, DistributedLoop ownerLoop) {
- super();
- this.START = start;
- this.END = end;
- this.OWNER = ownerLoop;
- }
- public void run() {
- try {
- execLoop();
- } catch(Exception ex) {
- OWNER.passException(ex);
- }
- OWNER.readyCountUp();
- }
- protected void pass(@SuppressWarnings("unused") Object...data) {}
- protected abstract void execLoop() throws Exception;
- }
- /**
- * <p>Veraltetes Interface.</p>
- * <p>
- * Kann genutzt werden, wenn man beim beenden alle Threads in
- * eine andere Methode springen will.
- * </p>
- *
- * @version 1.0.0.1
- * @author Linux-Fan, Ma_Sys.ma
- * @deprecated
- * Mittlerweile ist es möglich, dass {@link DistributedLoop#startAll()}
- * auf das Beenden der Threads wartet, ohne einen eigenen Wartethread zu
- * erzeugen.
- */
- interface DistributedLoopUser {
- public void distributedThreadsReady(Exception[] passed);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement