ThreadUtils

ThreadUtils

Da es in Java ja nicht möglich ist einen Thread zu Stopen und den Selben Thread später erneut nochmal auszuführen (anhand von befehlen wie start und stop) habe ich eine Jar erstellt die das ermöglicht. Der Thread wird gehalten bis DestroyThread(); aufgerufen wird. Hier ein Kleines Beispiel

package Programm;

import ThreadUtils.*;

import java.lang.Thread;

/**
 * Created by Andreas on 22.07.14.
 */
public class Main {

    public static void main(String[] args)
    {
        TThread thread = new TThread();
        System.out.println("Durchlauf 1");
        thread.ThreadStart();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        thread.ThreadStop();

        System.out.println("Durchlauf 2");
        thread.ThreadStart();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        thread.ThreadStop();

        System.out.println("Durchlauf 3");
        thread.ThreadStart();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        thread.ThreadStop();
        thread.DestroyThread();
    }

}

class TThread extends ThreadUtils.Thread
{
    @Override
    public void ThreadRun()
    {
        System.out.println("1");
        System.out.println("2");
        System.out.println("3");
    }
}

Ich weiß es ist nicht viel aber vielleicht Hilfreich. Download

Wo liegt der Vorteil zu

Runnable r = new Runnable() {
   public void run() {
        System.out.println("1");
        System.out.println("2");
        System.out.println("3");
   }
}

System.out.println("Durchlauf 1");
new Thread(r).start();  
try {
  Thread.sleep(1000);
} catch (InterruptedException e) {
   e.printStackTrace();
}

System.out.println("Durchlauf 2");
new Thread(r).start();  
try {
  Thread.sleep(1000);
} catch (InterruptedException e) {
  e.printStackTrace();
}

System.out.println("Durchlauf 3");
new Thread(r).start();  

?

Ich meine, Threads sollten prinzipiell nicht von außen gestoppt werden, sondern das selber (ggf. über Infromationen von außen) tun. Und den Code kann man problemlos wiederverwenden, wie obiges Beispiel zeigt.

Je nach Anwendungsfall gibt es weitergehende Abstraktionen, die auf Threads aufsetzen (Threadpools, Executor-Framework, Producer-Consumer u.s.w.). Ich selbst setze Threads deshalb nur da ein, wo ich wirklich nur eine dumme Fire-And-Forget-Funktionalität brauche. Sobald etwas Komplizierteres gefragt ist, suche ich mir lieber die geeignete “höhere” Abstraktion.

Ich finde es vorteilhaft wenn man einen Thread nach belieben weiterlaufen lassen kann. Soll ja nur Optional sein, wenn man eine Solche Thread methode benötigt.

In den meisten Fällen reicht wirklich das Runnable mit „Fire and Forget“, evtl. noch als deamon.
Allerdings würde ich mich nicht als Threading-Experte bezeichnen :smiley:

Für einfache Zwecke tut es auch sowas in der Art:
Das sieht man in unterschiedlichen Ausbaustufen (bessere Zeitmessung, mehr Controlling, …) auch in Game-Loops.


	private static final int UPDATE_TIME_MS = 33;
	volatile boolean isPaused = false;
	volatile boolean isStopped = false;

	@Override
	public void run() {
		while (!isStopped) {
			if (!isPaused) {
				doLogicLoop();
			}
			try {
				Thread.sleep(UPDATE_TIME_MS);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

	abstract void doLogicLoop();
}```

Dein Download funktioniert übrigens nicht.

Sehe ich ganz genauso. Java bietet viele Möglichkeiten, um parallel zu arbeiten. Für die Synchronisation gibt es auch High-Level-Mechanismen in sämtlichen Geschmacksrichtungen, die man wunderbar einsetzen kann.

Und genau dafür gibt es diese Synchronisationsmechanismen. Damit kann man einen Thread genau so lange blockieren ((fast) ohne Ressourcen zu verbrauchen), bis das Ereignis eingetroffen ist, auf das man wartet.

(Methodennamen schreibt man im kleinenCamelCase!!!einseinselfausrufezeichenaueseruefezetteizehhaeen)

Der Download geht nicht, ja.

Ansonsten ist “sowas” schon praktisch: Diese Start/Pause/Stop-Funktionalität musste ich auch schon gelegentlich implementieren. Und es ist immer wieder frickelig…

    /**
     * The lock for the 'paused' state
     */
    private final Lock pausedLock = new ReentrantLock(true);
    
    /**
     * The condition that the work was unpaused
     */
    private final Condition unpaused = pausedLock.newCondition();
    
    /**
     * The lock for the 'running' state
     */
    private final Lock runningLock = new ReentrantLock();
    
    /**
     * The condition that the work finished
     */
    private final Condition finishedRunning = runningLock.newCondition();
    
    /**
     * Whether the thread should stop as soon as possible
     */
    private volatile boolean stopped = false;
    
    /**
     * Whether the work is paused
     */
    private volatile boolean paused = false;
    
    /**
     * Whether the work is currently running
     */
    private volatile boolean running = false;

    /**
     * The thread
     */
    private volatile Thread thread;

...
  • natürlich das GUI, mit den Start/Stop/Pause-Buttons, die ensprechend enabled/disabled werden. Ich hab’s schon relativ weit zu einem “Template” gemacht, so, dass man es für verschiedene Aufgaben in ähnlicher Form verwenden kann, aber immernoch auf Codeseite, und nicht als “Library”. (Obwohl da nicht mehr so viel fehlt…)

Habe hier mal der Download im Anhang, leider konnte ich den Startpost nicht editieren, sonst würde Ich ihn dort ergänzen.

Dann will ich mal meinen Senf dazu geben:

paketname: all-lowercase und beginnen am besten mit der “umgekehrten Domain”.
Namensgebung für Klassen: man sollte keine Namen verwenden die bereits in deiner Bibliothek verwendet werden.
Felder/Variablen/Methoden: sind lowerCamelCase zu schreiben

Desweiteren:
Die run-Methode wäre wohl besser Final
Die Methode ThreadRun und die Klasse an sich würde ich abstrakt machen.
Getter für boolean beginnen normal mit is. GetThreadState() würde ich in isThreadRunning() umbennen.

Fatal:
ThreadStop pausiert den Thread nur und dürfte für eine hohe Prozessorauslastung sorgen (aufgrund der leeren while-Schleife).

Anmerkung:
ThreadDestroy zerstört deinen Thread nicht wirklich, er stoppt ihn. Das Thread-Objekt wird aber weiterhin existieren.

Ja, den Code hab’ ich mir jetzt auch mal angesehen. räusper. Ergänzend zu dem, was Tomate_Salat schon gesagt hat: Zwei booleans (die nicht volatile sind) und drei Methoden, die busy waiting verstecken? Das ist eigentlich genau das, was man NICHT machen sollte. Viel mehr sag’ ich jetzt erst mal nicht dazu…