Cel: pokazać, że brak synchronizacji daje błędne wyniki.
Kroki:
synchronized.AtomicInteger i porównaj czytelność.Szkielet:
int threads = 8; int increments = 100_000; // uruchomienie wielu wątków i join // wypisanie: expected = threads * increments
Wskazówki:
join() dla wszystkich wątków.Wersja poprawna (AtomicInteger):
import java.util.concurrent.atomic.AtomicInteger; class AtomicCounter { private final AtomicInteger value = new AtomicInteger(); void inc() { value.incrementAndGet(); } int get() { return value.get(); } }
Cel: komunikacja wait/notifyAll na monitorze.
Zakres:
sleep jako mechanizmu synchronizacji).Wskazówki:
put() i take() jako synchronized.while.OneSlotBuffer buffer = new OneSlotBuffer(); Thread producer = new Thread(() -> { for (int i = 1; i <= 10; i++) { try { buffer.put(i); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } }); Thread consumer = new Thread(() -> { for (int i = 1; i <= 10; i++) { try { System.out.println(buffer.take()); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } }); producer.start(); consumer.start();
Wybierz jedno zadanie. Każde zawiera wersję podstawową i rozszerzenie.
Wymagania:
Counter i uruchom 6 wątków po 50_000 inkrementacji.System.nanoTime().Wskazówki:
join().AtomicInteger albo synchronized.Rozwiązanie (minimum):
// expected = 300_000 // brokenCounter -> zwykle mniej // fixedCounter -> dokładnie 300_000
Wymagania:
int[].Wskazówki:
join().ExecutorService + Callable<Long>.Rozwiązanie (minimum):
// podziel [0, n) na k przedziałów // submit Callable<Long> // sumuj wyniki z Future.get()
Wymagania:
Thread.sleep(…)).Wskazówki:
Semaphore(3) albo Executors.newFixedThreadPool(3).finally.Rozwiązanie (minimum):
ExecutorService pool = Executors.newFixedThreadPool(3); for (String file : files) { pool.submit(() -> { System.out.println("START " + file + " " + Thread.currentThread().getName()); Thread.sleep(500); System.out.println("END " + file + " " + Thread.currentThread().getName()); }); } pool.shutdown();
Wymagania:
Wskazówki:
lockA, lockB.lockA, potem lockB.Zaimplementuj klasę, która wykorzystując wątki pozwoli na podanie sumy wszystkich elementów w tablicach wygenerowanych losowo. Użytkownik ma mieć możliwość określenia długości tablic i ich liczby.
Zaimplementuj klasę statyczną, która z wykorzystaniem wielu wątków pozwoli wykonywanie mnożenia dwóch macierzy przechowywanych w postaci tablic dwuwymiarowych. Zadbaj o to, aby przed rozpoczęciem operacji sprawdzić, czy mnożenie macierzy można w ogóle wykonać.
Zaimplementuj klasę statyczną, która pozwoli z wykorzystaniem wielu wątków doprowadzić macierz przechowywaną w postaci tablicy dwuwymiarowej do postaci górnotrójkątnej (eliminacja Gaussa). Dodatkowe 3 pkt. otrzymać można za doprowadzenie macierzy do postaci zdiagonalizowanej. Przed wykonaniem operacji sprawdź, czy spełnione są warunki niezbędne do tego, aby operacja się powiodła.