Cześć, mam za zadanie stworzyć tablice, a następnie podzielić ją na zakresy i poszukać w niej minimum lokalnego i maksymalnego za pomocą wątków (liczbę podaje użytkownik). Nie mogę użyć kolekcji, ani list. Na końcu z minimum lokalnego i maksimum wyznaczyć min i max dla całej tablicy. Ma ktoś jakiś pomył jak to zrobić? Próbowałem na wiele sposobów, ale każdy nadpisuje mi zmienne globalne i wychodzi od razu minimum i maksimum dla całej tablicy. Nie wiem jak zrobić to inaczej nie używając tych zmiennych globalnych.
- Rejestracja:ponad 10 lat
- Ostatnio:5 miesięcy
- Lokalizacja:Warszawa
- Postów:3573
Bo nie powinieneś korzystac z zadnych zmiennych globalnych! Z każdego zakresu zwracasz minimalna i maksymalna liczbę a później z tej grupy wybierasz min/maks. ExecutorService + Callable bym użył.

- Rejestracja:około 21 lat
- Ostatnio:prawie 3 lata
- Lokalizacja:Space: the final frontier
- Postów:26433
A co ty tam chcesz trzymać w zmiennych globalnych? o_O Użyj Callable<T>
i zwracaj wynik cząstkowy z danego wątku, a nie wpisuj go gdzieś do zmiennej globalnej.
- Rejestracja:ponad 6 lat
- Ostatnio:ponad 4 lata
- Postów:22
Shalom napisał(a):
A co ty tam chcesz trzymać w zmiennych globalnych? o_O Użyj
Callable<T>
i zwracaj wynik cząstkowy z danego wątku, a nie wpisuj go gdzieś do zmiennej globalnej.
Bo zmiennych globalnych używam do przekazania ile ma być wątków i od jakich do jakich wartości szukać w funkcjach. Jak zrobię voida to nie będę mógł tego wywołać dla każdego wątku, tak, żeby wynik wyszedł mi poprawny. Zresztą nie mam pomysłu jak to zrobić, przejrzałem setki kodów i w każdym jest coś przypisywane do zmiennych globalnych, a z wątkami wcześniej nie pracowałem i ciężko mi to idzie.
- Rejestracja:ponad 10 lat
- Ostatnio:5 miesięcy
- Lokalizacja:Warszawa
- Postów:3573
@klonstoper:
Robisz jakąs klase MinMax która zwiera parę minimalnej i maksymalnej wartości i robisz klase
public final class FindLocalMinMax implements Callable<MinMax> {
private final E[] array//E to Twój typ tablicy
private final int leftIndex; //początek przedziału
private final int rightIndex; //koniec przedziału
// tu powinien być konstrutor
public MinMax call() {
//tu se szukasz
}
}
Później każdtego callabla przekazujesz do ExecutorServica robisz submita, z niego masz Future z którego getem będziesz mogł pobrać rezultat (tylko najpierw trzeba zsubmitować wszystkie taski żeby to miało sens)
- Rejestracja:prawie 10 lat
- Ostatnio:około 3 godziny
- Postów:2368
1 konsument (np. MinMaxFinder/ParallelMinMaxFinder/BlockingParallelMinMaxFinder/MojSzukacz
etc.) + N producentów (np. MinMaxWorker
)
- Konsument wie ilu ma być producentów (N), zna currentMin, currentMax (inicjalnie - pierwszy element przeszukiwanej tablicy), zna przeszukiwaną tablicę
- Konsument wie ilu odpowiedzi ma się spodziewać (N), aktualizuje min/max na podstawie tego co dostaje od producenta
- Konsument tworzy N producentów i przydziela im zakres do przetworzenia
- Każdy producent zna konsumenta do którego ma przekazać dane i zakres, który ma przetworzyć
W siermiężny sposób na konsumencie możesz mieć metodę synchronized
-> updateMinMax(computedMin,computedMax)
, którą wołają producenci jak skończą przetwarzać zakres...
W tej metodzie zwiększasz licznik odpowiedzi, które otrzymałeś, aktualizujesz min/max.
Konsumpcję można synchronizować inaczej, ale nie wiem co ćwiczyliście na zajęciach ;-)

- Rejestracja:prawie 5 lat
- Ostatnio:prawie 5 lat
- Postów:10
Typowe zadania na ForkJoina, poczytaj o tym
- Rejestracja:ponad 10 lat
- Ostatnio:5 miesięcy
- Lokalizacja:Warszawa
- Postów:3573

- Rejestracja:prawie 8 lat
- Ostatnio:3 miesiące
- Postów:205
scibi92 napisał(a):
@Henryk VIII Tudor: no chyba nie bardzo. ForkJoin jest do rekursji i bardzije nadaje się np. do Merge Sort, a tu nie ma rekursji :)
ForkJoin jak najbardziej tutaj można użyć, implementując RecursiveTask
, który odpowiednio będzie dzielił wejściową tablicę na mniejsze porcje (faza fork) i potem łączył rezultaty, wyznaczając min i max (faza join).
- Rejestracja:ponad 10 lat
- Ostatnio:5 miesięcy
- Lokalizacja:Warszawa
- Postów:3573
MergeSort jest oparty o rekursję, więc RecuirsiveTask się nada. Tutaj stosowanie RT jest overkillem i strzelaniem z armaty do muchy, po po prostu dzielicz sobie tablice na równe części i tyle...
- Rejestracja:ponad 6 lat
- Ostatnio:7 dni
- Postów:3561
- Rejestracja:ponad 6 lat
- Ostatnio:ponad 4 lata
- Postów:22
Zrobiłem szukanie minimum i maksimum lokalne, na razie zwykłym run, pomyślę jak rozwiążę to z szukaniem w całości tablicy. Program jednak się nie kompiluje...
błąd:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
już nie wiem co jest źle...
kod:
import static java.lang.Math.*;
public class Zadanie3 implements Runnable {
private int id;
private int id2;
private int[] tab = new int[200000000];
public Zadanie3(int id){
this.id=id;
}
public Zadanie3(){
}
public void updateID(int id2){
this.id2=id2;
}
public void wypelnijTablice()
{
for (int i=0; i<tab.length; i++)
{
tab[i]=i;
}
}
public void run() {
int ilosc=(int)floor(200000000/(id2));
int koniec=ilosc*(id+1);
int poczatek=koniec-ilosc;
if (id==0){
poczatek=0;
koniec=ilosc;}
int maxl=tab[poczatek];
int minl=tab[poczatek];
for(int i=poczatek; i<=koniec; i++){
if(maxl>tab[i]){
maxl=tab[i];
}
}
for(int i=poczatek; i<=koniec; i++)
{
if (minl < tab[i]) {
minl = tab[i];
}
}
System.out.println("Watek numer: " +id+1 +"zakres: " +poczatek +"-"+koniec +", Max: " +maxl +", Min: " +minl);
}
}
import java.util.Scanner;
public class Runner extends Zadanie3 {
public Runner(int id) {
super(id);
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("Podaj ilosc watkow: ");
int ilosc_watkow = scanner.nextInt();
Zadanie3[] runners= new Zadanie3[ilosc_watkow];
Thread[] watki=new Thread[ilosc_watkow];
Zadanie3 id2 = new Zadanie3();
id2.wypelnijTablice();
id2.updateID(ilosc_watkow);
for(int i=0; i<ilosc_watkow; i++) {
runners[i] = new Zadanie3(i);
}
for(int i=0; i<ilosc_watkow; i++) {
watki[i] = new Thread(runners[i]);
}
for(int i=0; i<ilosc_watkow; i++) {
watki[i].start();
}
}
}
Dodatkowo id2 się nie aktualizuje, mimo, że przekazuje tam liczbę wątków.
- Rejestracja:prawie 10 lat
- Ostatnio:około 3 godziny
- Postów:2368
klonstoper napisał(a):
Zrobiłem szukanie minimum i maksimum lokalne, na razie zwykłym run, pomyślę jak rozwiążę to z szukaniem w całości tablicy. Program jednak się nie kompiluje...
błąd:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
- Jak się nie kompiluje, jak dostajesz błąd wykonania?
- Ile pamięci zajmuje tablica intów, którą tworzysz?
- Ile pamięci przydzielasz dla wirtualnej maszyny javy?
- Rejestracja:ponad 6 lat
- Ostatnio:ponad 4 lata
- Postów:22
yarel napisał(a):
- Jak się nie kompiluje, jak dostajesz błąd wykonania?
- Ile pamięci zajmuje tablica intów, którą tworzysz?
- Ile pamięci przydzielasz dla wirtualnej maszyny javy?
Nie uruchamia się, mój błąd.
200 megabajtów kalkulator wyliczył
Mam domyślne ustawienia IntelliJ (parametr -Xmx2048m)
- Rejestracja:prawie 10 lat
- Ostatnio:około 3 godziny
- Postów:2368
Jaki kalkulator wyliczył Ci 200 megabajtów?
Pomnóż to jeszcze przez liczbę wątków, bo tworzysz tę tablicę wielokrotnie -> new Zadanie3[ilosc_watkow]
. Przy 2048M na hepa, to pewnie Twój program wywali się przy 3 wątkach, właśnie na braku pamięci.
- Rejestracja:ponad 6 lat
- Ostatnio:ponad 4 lata
- Postów:22
yarel napisał(a):
Pomnóż to jeszcze przez liczbę wątków, bo tworzysz tę tablicę wielokrotnie ->
new Zadanie3[ilosc_watkow]
. Przy 2048M na hepa, to pewnie Twój program wywali się przy 3 wątkach, właśnie na braku pamięci.
A jak zrobię private int[] tab = new int[n]; i n przekażę w metodzie updateID?
Problem w tym, że id2 się i tak nie aktualizuje przy takim wywołaniu jak mam. Da się jakoś zrobić tak, żebym z każdym wątkiem nie tworzył tej tablicy wielokrotnie, przy takiej konstrukcji jak mam i id2 podane raz było dla całej tablicy obiektów?
- Rejestracja:prawie 10 lat
- Ostatnio:około 3 godziny
- Postów:2368
klonstoper napisał(a):
...
Problem w tym, że id2 się i tak nie aktualizuje przy takim wywołaniu jak mam.
A co to znaczy, że "id2 się nie aktualizuje" i jakiego zachowania oczekujesz?
Da się jakoś zrobić tak, żebym z każdym wątkiem nie tworzył tej tablicy wielokrotnie, przy takiej konstrukcji jak mam i id2 podane raz było dla całej tablicy obiektów?
Da się. Do tworzonego wątku można przekazać parametry prze konstruktor bądź przez wywołanie metody z tymi parametrami.
- Rejestracja:ponad 6 lat
- Ostatnio:ponad 4 lata
- Postów:22
yarel napisał(a):
A co to znaczy, że "id2 się nie aktualizuje" i jakiego zachowania oczekujesz?
Oczekuję, że metodą updateid przekaże ilość wątków do id2 w klasie Zadanie3, i w run() dla każdego wątku(id) id2 będzie równe liczbie wszystkich wątków, co pozwoli zadziałać tym wątkom tak jak oczekuje. Na razie ani uzupelnianie tabeli nie działa, ani przekazanie id2, a robię to właśnie obiektem wywołanym domyślnym konstruktorem, a nie wątkiem.

- Rejestracja:prawie 5 lat
- Ostatnio:prawie 5 lat
- Postów:10
Ja takie cos na szybko napisalem na maksa.
Jak chcesz tez minimum to jakas Pare stworzyc, czy z biblioteki wziąć.
Jest algorytm na szukanie min i maks jednocześnie o złożoności (1/2N) to możesz to też zmienić).
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;
import java.util.concurrent.ThreadLocalRandom;
class MaximumSeeker extends RecursiveTask<Integer> {
private static final int THRESHOLD = 4;
private int[] arr;
private int low;
private int high;
public MaximumSeeker(int[] arr, int low, int high) {
this.arr = arr;
this.low = low;
this.high = high;
}
@Override
protected Integer compute() {
if (high - low <= THRESHOLD) {
return calcMax(arr, low, high);
}else{
int mid = low + (high - low) / 2;
var task = new MaximumSeeker(arr, low, mid);
task.fork();
return Math.max(new MaximumSeeker(arr, mid + 1, high).compute(), task.join());
}
}
private int calcMax(int[] arr, int low, int high) {
int max = 0;
for (int i = low; i <= high; i++) {
if (arr[i] >= max) {
max = arr[i];
}
}
return max;
}
public static void main(String[] args) {
var pool = new ForkJoinPool();
var arr = new int[]{5,4,2,1,10,22,41,43,9,23,11};
var max = pool.invoke(new MaximumSeeker(arr, 0, arr.length - 1));
System.out.println(max);
}
}