Vícevláknové aplikace
Proč to potřebuji?
Vícevláknové programování umožňuje provádět více úloh současně, což je nezbytné pro responzivní GUI aplikace, servery a efektivní využití vícejádrových procesorů. Správná synchronizace je klíčová pro předcházení chybám.
Teorie
Vlákno (thread) = nejmenší jednotka provádění v rámci procesu. Vlákna sdílejí paměť procesu, což přináší výkon i rizika (race conditions).
Vytvoření: rozšíření Thread nebo implementace Runnable. Moderní přístup: ExecutorService.
Synchronizace: synchronized blok/metoda zamkne přístup pro ostatní vlákna. Prevence race conditions.
Příklady
import java.util.concurrent.*;
// === Způsob 1: Runnable ===
Runnable uloha = () -> {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + ": " + i);
try { Thread.sleep(100); } catch (InterruptedException e) { break; }
}
};
Thread t1 = new Thread(uloha, "Vlákno-1");
Thread t2 = new Thread(uloha, "Vlákno-2");
t1.start(); // spuštění vlákna
t2.start();
t1.join(); // čekání na dokončení
t2.join();
// === Synchronizace – sdílený čítač ===
class BezpecnyCitac {
private int hodnota = 0;
// synchronized metoda – jen jedno vlákno najednou
public synchronized void zvys() {
hodnota++;
}
public synchronized int getHodnota() {
return hodnota;
}
}
// Bez synchronized: race condition – výsledek je nepředvídatelný
// Se synchronized: vždy správný výsledek
// === ExecutorService – moderní přístup ===
ExecutorService executor = Executors.newFixedThreadPool(3);
// Odeslání úloh
Future<Integer> vysledek = executor.submit(() -> {
Thread.sleep(1000);
return 42;
});
executor.execute(() -> System.out.println("Běží na poolu"));
// Získání výsledku (blokující)
int hodnota = vysledek.get(); // čeká na dokončení, vrátí 42
// Ukončení poolu
executor.shutdown();
executor.awaitTermination(5, TimeUnit.SECONDS);
// === Synchronized blok (jemnější zamykání) ===
class Sklad {
private final List<String> polozky = new ArrayList<>();
private final Object zamek = new Object();
public void pridej(String polozka) {
synchronized (zamek) {
polozky.add(polozka);
}
}
public String odeber() {
synchronized (zamek) {
if (polozky.isEmpty()) return null;
return polozky.remove(0);
}
}
}
Shrnutí
Klíčové body
Thread/Runnable– vytvoření vlákna,start()– spuštěnísynchronized– zamezí souběžnému přístupu (prevence race condition)ExecutorService– pool vláken,Futurepro návratovou hodnotujoin()– čekání na dokončení vlákna