Threadsafe

Collections:
unmodifiable, immutable, kann gar nicht verändert werden
synchronized, ist ein synchronisierter wrapper

Atomic Integer / Long
ThreadLocal: Jeder Thread kriegt seine eigene Instanz
ThreadLocalRandom: Jeder Thread kriegt sein eigenes Random

Executor Service

Hat einen Threadpool, der die Threads verwaltet, wenn eine neue Aufgabe kommt, wird ein Thread aus dem Pool genommen und die Aufgabe ausgeführt. Wenn kein Thread verfügbar ist kommen die Aufgaben in eine Queue.

// genau einen Thread im Pool
ExecutorService executor = Executors.singleThreadExecutor();
// bestimmte Anzahl an Threads
ExecutorService executor = Executors.newFixedThreadPool(10);
// keine obere grenze, aber threads im pool bleiben offen. Wenn ein Thread länger als 60 Sekunden nicht benutzt wird, wird er geschlossen.
ExecutorService executor = Executors.newCachedThreadPool();

Runnable task = ()  -> {
    System.out.println("Running task");
};
executor.execute(task);
// führt alle Aufgaben aus und schließt den Threadpool, non-blocking
executor.shutdown();
// wartet, blockiert
executor.awaitTermination(3, TimeUnit.SECONDS);