Concurrency Flashcards
(35 cards)
Stel, we hebben een thread:
Thread myThread = new Thread();
Wat moeten we uitvoeren om deze thread af te trappen?
myThread.start();
niet te verwarren met .run();
Welke interface implementeert Tread?
Runnable
Wat is de enige abstract method van de Runnable interface? En wat returnt het?
.run();
het returnt void.
Wat is de enige abstract method van de Callable interface? En wat returnt het?
.call()
het returnt een generic die in de interface is geimplementeerd. Dus, wanneer we Callable implementeren dienen we bijvoorbeeld te zeggen:
public class myClass implements Callable<Person>
En dan de call() method:
public Person call() { return new Person("Harry", 22); }
Wat kunnen we doen met Runnable en Callable?
Taken uitvoeren die in aparte threads kunnen worden uitgevoerd.
Werkt de volgende code? Waarom wel / niet?
Thread foo = new Thread(() -> { Thread.sleep(1000); System.out.println("Foo Thread"); });
Dit compileert niet omdat de .sleep()
een checked exception gooit (InterruptedException). Moet dus in een try/catch:
Thread foo = new Thread(() -> { try { Thread.sleep(1000); } catch (InterruptedException e) { throw new RuntimeException(e); } System.out.println("Foo Thread"); });
Stel, we hebben deze code:
static int count = 0; public static void main(String[] args) { for (int i = 0; i < 10; i++) { Thread t = new Thread(() -> incrementCount()); } } static void incrementCount() { count++; }
Wat is na het uitvoeren van de for loop de waarde van count?
0
.
Let erop dat t
niets doet tenzij je de thread ook daadwerkelijk start met t.start();
Stel, we hebben deze code:
static int count = 0; public static void main(String[] args) { for (int i = 0; i < 10; i++) { Thread t = new Thread(() -> incrementCount()); t.start(); } } static void incrementCount() { count++; }
Dit levert geen betrouwbare resultaten op. Hoe zorg ik ervoor dat incrementCount maar door 1 thread tegelijk afgetrapt mag worden?
Door syncronized toe te voegen aan incrementCount:
syncronized static void incrementCount() { count++; }
Wat doet een ReentrantLock
?
De ReentrantLock implementeert de Lock interface en kan ervoor zorgen dat een bepaald stuk code maar 1 keer tegelijk aangetrapt wordt. Bijvoorbeeld:
public class Main { static Lock lock = new ReentrantLock(); public static void main(String[] args) { for (int i = 0; i < 10; i++) { Thread t = new Thread(() -> incrementCount()); t.start(); } } static void incrementCount() { lock.lock(); // Dingen die maar in 1 thread tegelijk mogen gebeuren lock.unlock(); }
wat doet tryLock op een ReentrantLock? (zonder parameters)
wat geeft het terug?
tryLock probeert een lock te zetten. Als dit lukt geeft het een waarde van true terug (en lockt het vervolgens), en zo niet een waarde van false.
Op deze wijze kunnen we ervoor zorgen dat een stuk functionaliteit op 1 moment tegelijk mag draaien, en kunnen we een fallback maken voor wanneer dit stuk code al ‘in gebruik’ is.
wat doet tryLock op een ReentrantLock? (met parameters)
wat geeft het terug?
welke parameter(s) moeten we opgeven?
tryLock probeert een lock te zetten. Als dit lukt geeft het een waarde van true terug (en lockt het vervolgens), en zo niet een waarde van false.
tryLock met parameters geeft een tijdslimiet aan; die aangeeft hoe lang er gewacht moet worden. Na deze limiet is het resultaat false.
De parameters zijn tijd en tijdsunit. Bijvoorbeeld:lock.tryLock(2000, TimeUnit.MILLISECONDS)
Naast MILLISECONDS heb je ook:
* NANOSECONDS
* MICROSECONDS
* SECONDS
* MINUTES
* HOURS
* DAYS
Let erop dat beide parameters vereist zijn.
Net als Thread.sleep gooit de tryLock ook InterruptedException; dus deze moet in de method signature of een try/catch worden afgehandeld.
Hoe maak in een enkele thread aan waar een actie op uitgevoerd kan worden.
Twee opties:
1: Met een nieuwe thread:
Thread foo = new Thread(() -> doStuff()); foo.start();
2: Door een singleThreadExecutor aan te maken.
private static ExecutorService executor = Executors.newSingleThreadExecutor(); public static void main(String[] args) { executor.submit(() -> doStuff()); }
Hoe voeren we taken uit binnen een x aantal thread pools?
met newFixedThreadPool. Bijvoorbeeld:
private static ExecutorService executor = Executors.newFixedThreadPool(5);
Wanneer we dan deze code hebben:
for (int i = 0; i < 10; i++) { executor.submit(() -> incrementCount()); }
Zal de executor van verschillende threads gebruik maken.
Wat doet de newCachedThreadPool? Welke interface implementeert het? Wat voor parameters neemt het op?
newCachedThreadPool implementeert ExecutorService en kan er als volgt uit zien:
private static ExecutorService executor = Executors.newCachedThreadPool();
Het neemt geen parameters op; en maakt een nieuwe thread aan wanneer de reeds aangemaakte threads bezet zijn en het systeem een nieuwe thread aan kan.
Wanneer kan een thread related object of method een InterruptedException gooien?
Wanneer er sprake is van een vertraging. Thread.sleep
, tryLock
, en .schedule
in een scheduledThreadPool zijn hier voorbeelden van.
Wat doet de newScheduledThreadPool? Welke interface implementeert het? Wat voor methods kunnen we erop loslaten en welke parameters vragen deze methods?
newScheduledThreadPool implementeert ScheduledExecutorService en kan er als volgt uit zien:
private static ScheduledExecutorService executor = Executors.newCachedThreadPool(50);
We kunnen als volgt van de executor gebruik maken:
Future<Double> myNumber = executor.schedule( () -> doSomething(), 1000, TimeUnit.MILLISECONDS )
Dit zegt dat doSomething over 1000 milliseconden moet worden uitgevoerd. Als doSomething een Double returnt, dan is het return type van myNumber dus Future<Double>.
met `myNumber.get(1500, TimeUnit.MILLISECONDS);` kan deze waarde worden opgehaald. (vergeet de InterruptedException niet af te vangen)</Double>
Collections als HashMap zijn niet geschikt voor gebruik in threads. Wat is de oplossing?
in plaats van HashMap kun je ConcurrentHashMap gebruiken; met dezelfde functionaliteit als HashMap, en thread support.
Wat is de Queue variant die gebruikt kan worden voor Threads?
De interface BlockingQueue, en het object LinkedBlockingQueue.
Stel, ik heb een ConcurrentSkipListSet:
Set<String> set = new ConcurrentSkipListSet<>(); set.add("Tim"); set.add("Pascal"); set.add("Elias"); for(String s: set) { System.out.println(s) }
In welke volgorde worden de items geprint?
Elias, Pascal, Tim.
ConcurrentSkipListSet heeft een auto sort die in ieder geval probeert een basic sortering (nummers oplopend, of strings alfabetisch) toe te passen.
Wat is een Map variant die gebruikt kan worden voor Threads?
ConcurrentSkipListMap. Is onderdeel van de Map interface.
Stel, ik heb een ConcurrentSkipListMap:
Map<String, String> map = new ConcurrentSkipListMap<>(); set.put("Guitar", "Tim"); set.put("Bass", "Pascal"); set.add("Piano", "Elias"); for(String s: map.keySet()) { System.out.println(s) }
In welke volgorde worden de items geprint?
Bass, Piano, Guitar.
ConcurrentSkipListMap heeft een auto sort die in ieder geval probeert een basic sortering (nummers oplopend, of strings alfabetisch) toe te passen. Dit betreft de keys, niet de values.
Wat is een List variant die gebruikt kan worden voor Threads?
CopyOnWriteArrayList. Is onderdeel van de List interface.
Wat is een Set variant die gebruikt kan worden voor Threads?
CopyOnWriteArraySet. Is onderdeel van de Set interface.
Wat is het voornaamste verschil tussen CopyOnWriteArrayList
en CopyOnWriteArraySet
?
De list kan duplicates bevatten. Wanneer we een item aan de set toevoegen die al bestaat gebeurt er simpelweg niets.