Concurrency Flashcards
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);
}
~~~</Person>
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.