Thread Management in Java

  1. Begriffsklärung
  2. Grundlegende Thread-Programmierung
  3. Weiterführende Konzepte

Gliederung

Begriffsklärung

Nebenläufig vs. Parallel

  • Prozess
    • Programminstanz mit eigenem Speicherbereich
    • Enthält immer >= 1 Thread
  • Thread
    • leichtgewichtiger Prozess

Nebenläufig vs. Parallel

nebenläufig

parallel

unabhängig

unabhängig

& gleichzeitig

Vorgänge

sind

{

Nebenläufig vs. Parallel

nur nebenläufig

auch parallel

verteilt

Grundlegende Thread-Programmierung

static class RunnableThread implements Runnable {
    @Override
    public void run() {
        // Thread-Logik
    }
}

Thread runnableThread = new Thread(new RunnableThread());

Erzeugen und Ausführen

static class ExtendedThread extends Thread {
    @Override
    public void run() {
        // Thread-Logik
    }
}

Thread extendedThread = new ExtendedThread();
try {
    Thread.sleep(1000);
    TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
    // ...
}

Pausieren

= Warten ohne Verschwendung von Prozessorressourcen

public static void main(String[] args)
    throws InterruptedException {
    
    Thread t = new Thread(() -> {
        // irgendeine Berechnung
    });
    t.start();
    t.join(1000);
}

Auf anderen Thread warten

Thread t = new Thread(() -> {
    // Endlose Schleife bis zum Unterbrechen.
    while (true) {
        if (Thread.interrupted()) {
            return;
        }
    }
});
t.start();
t.interrupt();
System.out.println("Unterbrechungsindikator ist"
        + (t.isInterrupted() ? "" : " nicht")
        + " gesetzt.");

Unterbrechen

interrupt()

isInterrupted()

!

?

interrupted()

Weiterführende Konzepte

  • ID
  • Name
  • Priorität
  • Status

1 <= x <= 10

Eigenschaften

von Thread-Objekten

Eigenschaften

von Thread-Objekten

Status

NEW

RUNNABLE

TERMINATED

WAITING

TIMED_WAITING

start()

interrupt()

join(n)

join()

Eigenschaften

von Thread-Objekten

Thread t = new Thread(() -> {});
System.out.printf("Id: %s\nName: %s\nPrioritaet: %s\nStatus: %s\n\n",
        t.getId(), t.getName(), t.getPriority(), t.getState());

t.setName("Calculator");
t.setPriority(1);
t.start();
System.out.printf("Name: %s\nPrioritaet: %s\nStatus: %s\n\n",
        t.getName(), t.getPriority(), t.getState());

t.interrupt();
t.join();
System.out.printf("Status: %s\n\n", t.getState());
Thread t = new Thread(() -> {});
System.out.printf(...


t.setName("Calculator");
t.setPriority(1);
t.start();
System.out.printf(...


t.interrupt();
t.join();
System.out.printf(...

Eigenschaften

von Thread-Objekten

Id: 11
Name: Thread-0
Prioritaet: 5
Status: NEW

Name: Calculator
Prioritaet: 1
Status: RUNNABLE

Status: TERMINATED

Ausgabe

Daemon-Threads

public static void main(String[] args) {
    Thread dt = new Thread(() -> {
        while (true) {}
    });
    dt.setDaemon(true);
    dt.start();
}

Daemon-Threads

public static void main(String[] args) {
    Thread dt = new Thread(() -> {
        while (true) {}
    });
    dt.setDaemon(true);
    dt.start();
    // Dieses Programm endet hier 
    // trotz der Endlosschleife im Daemon-Thread.
}

Thread-Gruppen

ThreadGroup parentGroup = new ThreadGroup("Parent");
new ThreadGroup(parentGroup, "Child");
new Thread(parentGroup, () -> {});

Thread-Factories

ThreadFactory threadFactory = r -> null;
Thread t = threadFactory.newThread(() -> {});

if (t == null) {
    System.out.println("Thread ist null.");
}

Thread-Factories

ThreadFactory threadFactory = r -> null;
Thread t = threadFactory.newThread(() -> {});

if (t == null) {
    System.out.println("Thread ist null.");
}
// Gibt "Thread ist null." aus.

Ausnahmebehandlung

static class UncaughtExceptionHandler
        implements Thread.UncaughtExceptionHandler {
    @Override
    public void uncaughtException(Thread t, Throwable e) {
        System.out.printf("Look! A %s!\n", e);
    }
}

Ausnahmebehandlung

static class ExceptionThread implements Runnable {
    @Override
    public void run() {
        try {
            throw new InterruptedException();
        } catch (InterruptedException e) {
            throw new NumberFormatException();
        }
    }
}

public static void main(String[] args) {
    Thread exceptionT = new Thread(new ExceptionThread());
    exceptionT.setUncaughtExceptionHandler(
            new UncaughtExceptionHandler());
    exceptionT.start();
}

Ausnahmebehandlung

static class ExceptionThread implements Runnable {
    @Override
    public void run() {
        try {
            throw new InterruptedException();
        } catch (InterruptedException e) {
            throw new NumberFormatException();
        }
    }
}

public static void main(String[] args) {
    Thread exceptionT = new Thread(new ExceptionThread());
    exceptionT.setUncaughtExceptionHandler(
            new UncaughtExceptionHandler());
    exceptionT.start();
    // Gibt "Look! A java.lang.NumberFormatException!" aus.
}

Datenlokalität

static class LocalDataRunnable implements Runnable {


    Date dateShared = new Date();

    @Override
    public void run() {

        System.out.printf("[dateShared] %s\n", dateShared);
    }
}

Datenlokalität

static class LocalDataRunnable implements Runnable {
    private static ThreadLocal<Date> dateLocal
            = ThreadLocal.withInitial(Date::new);
    Date dateShared = new Date();

    @Override
    public void run() {
        System.out.printf("[dateLocal] %s\n", dateLocal.get());
        System.out.printf("[dateShared] %s\n", dateShared);
    }
}

Datenlokalität

public static void main(String[] args) throws InterruptedException {
    Thread t1 = new Thread(new LocalDataRunnable()),
            t2 = new Thread(new LocalDataRunnable());
    t1.start();
    t1.join();
    TimeUnit.SECONDS.sleep(2);
    t2.start();
    t2.join();
}
[dateLocal] Fri Nov 01 20:00:00 CET 2019
[dateShared] Fri Nov 01 20:00:00 CET 2019
[dateLocal] Fri Nov 01 20:00:02 CET 2019
[dateShared] Fri Nov 01 20:00:00 CET 2019

Ausgabe

Zusammenfassung

Thread Management in Java

By Jonas Thelemann

Thread Management in Java

  • 63