Mit ThreadPoolExecutor Arbeit unter Java effizient parallelisieren

Es gibt immer wieder Aufgaben, die sehr lange dauern und sehr große Mengen an Daten verarbeiten müssen. Dabei geht es meistens um Minuten oder gar Stunden, Tage …

Diese sollten sinnvollerweise parallelisiert werden, um die Leistungs des Systems zu nutzen. Heutige Systeme sind sehr oft Mehrkern- bzw. Mehrprozessorsysteme. Auch ist das GHz-Rennen im Moment zu Ende und die Leistung steigt über die Anzahl der Prozessoren bzw. Kerne.

Das folgende Beispiel zeigt wie man unter Java Aufgaben parallel verarbeiten kann, ohne sich groß den Kopf um die Ausführung zerbrechen zu müssen. Der ThreadPoolExecutor ist meiner Meinung nach eine sehr gute Möglichkeit Aufgaben zu parallelisieren, die Parallel ausgeführt werden können. Der große Vorteil ist, dass er Threads für das Abarbeiten am laufen hält. Das bedeutet bei neuen Aufgaben werden normalerweise keine Threads gestartet und somit entfällt faktisch dieser Overhead. Threads im Pool werden nur beendet, wenn sie länger als der festgelegte Timeout nicht benutzt werden oder sie vom Programmierer explizit beendet werden.

Nicht erschrecken. Das meiste davon sind Kommentare und Beispielcode.

Ich weiß – weniger Gelaber und her mit dem Code!

[code]
import java.util.concurrent.*;

class MyThreadPoolExecutor
{
//Parallel running Threads(Executor) on System
int corePoolSize = 2;

//Maximum Threads allowed in Pool
int maxPoolSize = 4;

//Keep alive time for waiting threads for jobs(Runnable)
long keepAliveTime = 10;

//This is the one who manages and start the work
ThreadPoolExecutor threadPool = null;

//Working queue for jobs (Runnable). We add them finally here
final ArrayBlockingQueue workQueue = new ArrayBlockingQueue(5);

public MyThreadPoolExecutor() {
threadPool = new ThreadPoolExecutor(corePoolSize, maxPoolSize,
keepAliveTime, TimeUnit.SECONDS, workQueue);
}

/**
* Here we add our jobs to working queue
*
* @param task a Runnable task
*/
public void runTask(Runnable task) {
threadPool.execute(task);
System.out.println(„Tasks in workQueue..“ + workQueue.size());
}

/**
* Shutdown the Threadpool if it’s finished
*/
public void shutDown() {
threadPool.shutdown();
}

public static void main(String args[]) {
MyThreadPoolExecutor mtpe = new MyThreadPoolExecutor();

for (int i= 0; i < 6; i++ ) { mtpe.runTask(new WorkerRunnable(i)); } mtpe.shutDown(); System.out.println("Finished! :)"); } /** * This is the one who do the work * * This one is static for accessing from main class */ private static class WorkerRunnable implements Runnable { //so we can see which job is running private int jobNr; /** * This is for understanding only * * @param jobNr number for displaying */ public WorkerRunnable(int jobNr) { this.jobNr = jobNr; } @Override public void run() { for(int i = 0; i < 10; i++) { try { System.out.println("Thread "+jobNr+" calculated "+ i); Thread.currentThread().sleep(1000); } catch (InterruptedException ie) { ie.printStackTrace(); } } } } } [/code] Da in diesem Beispiel die Anzahl der Parallel laufender Threads (corePoolSize) auf statisch 2 begrenzt ist, sollte die Zahl über Prozessoranzahl (siehe hier) bestimmt werden. Auch sollte man nicht vergessen die maximale Anzahl an Threads (maxPoolSize) entsprechend anzupassen.

3 Gedanken zu „Mit ThreadPoolExecutor Arbeit unter Java effizient parallelisieren

  1. Hei Konsi, es ist immer wieder klasse das ich wieder mal auf deine Seite stoße: erst die Handy-Connection, nun die Java-Instruktionen.

    Mal schauen wie gut ich mit den Infos klarkomme, ich habe grade die Aufgabe eine Queue für Aufgaben, die auf einer DB ausgeführt werden, zu implementieren.

    Viele Grüße erstmal!
    chris

  2. Zwei Methoden haben keinen Rückgabetyp. Es sollte schon wenigstens ein void stehen.
    Zeile 19 und 20 geht bei mir nur so: „final ArrayBlockingQueue workQueue = new ArrayBlockingQueue(5);“
    Dennoch gute Arbeit!

  3. Ja, WordPress findet da ein XML Tag und hat ein close tag rein. Ich habe den code verändert, damit wordpress es nicht mehr macht. Allerdings gibt das eine Warnung ab Java 5/6, das nicht genau spezifiziert ist, welche Element die ArrayBlockingQueue aufnehmen wird.

    Gruß, Konstantin

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.