Szálat indítani több módon is lehetséges:
Thread
-ből származtatással:
class MyThread extends Thread {
@Override
public void run() {
...
}
}
class Program {
public static void main(String[] args) {
MyThread mt = new MyThread();
mt.start(); // elindul a szál, futtatja a run()-t
}
}
Runnable
implementálásával:
class Task implements Runnable {
@Override
public void run() {
...
}
}
class Program {
public static void main(String[] args) {
Task task = new Task(); // t-nek nincs start() metódusa
// mt.start(); // fordítási hiba
Thread t = new Thread(task);
t.start() // elindul a sál, futtatja task.run()-t
}
}
Lambda függvénnyel:
class Program {
public static void main(String[] args) {
Thread t = new Thread(() -> {
... // paraméter nélküli, void eredményű lambda
});
t.start() // elindul a sál, futtatja a lambdát
}
}
A szinkronizációnak Javában két szerepe van:
összehangolja a szálak futását: egy szinkronizált metódust vagy blokkot egyszerre csak egy szál hajthat végre. A többinek várnia kell.
megszabja, melyik szál mit lát a memóriában. A szálak saját cache-sel dolgoznak, mely elavulttá válik. A szinkronizációs blokkba való belépéskor a cache-be frissül. Lásd RegularMap és a hozzá tartozó Point osztályokat.
Készíts egy több szálon futó map
implementációt!
A parMap
paraméterül kap egy sorozatot (tömb vagy lista) és egy egyparaméteres műveletet. A művelet végrehajtása történjen több szálon, minden elemre indítsunk egy szálat. Az eredmények begyűjtése sorban történjen: ha a sorozat x1
, x2
, x3
volt és a művelet f
, akkor az eredmény legyen f(x1)
, f(x2)
, f(x3)
.
A szálak paraméterül kapják a végrehajtandó műveletet, egy xn
elemet, az n
sorszámot, és egy adatszerkezetet, ahová az eredményt tehetik (például egy Map
, melynek tartalma 1 -> f(x1), 2 -> f(x2), 3 -> f(x3)
).
Alakítsuk át az előző programot, hogy ExecutorService
-t használjon! Ezzel korlátozható az elindított szálak száma, nem lassul be a számítógép.
A szálak visszaadhatják az f(xn)
eredményt egy Future
objektumon keresztül. Ehhez az ExecutorService
submit
metódusát használjuk. Ilyenkor nem kell mást átadni a szálaknak, csak a végrehajtandó f
műveletet, és egy xn
elemet, melyre meghívható f
.
Készíts programot, mely fájlokat ír felül véletlenszerű karaktersorozattal. A fájlok írása konkurrensen történjen, minden fájlhoz induljon egy szál. Enter billentyű megnyomására fejeződjön be a fájlok írása. A fájlokat vehetjük paranccsori argumentumokból vagy bekérhetjük a billentyűzetről.
Tipp: a szálak megállításához használjunk AtomicBoolean
-t. Rendszeresen nézzük meg az értékét, hogy meg kell-e állni.
Vegyük észre, hogy az AtomicBoolean
írásakor és olvasásakor nincs szükség explicit szinkronizációra, mert az a háttérben megtörténik.