Znaleźć maksymalny i minimalny element tablicy - wątki

Znaleźć maksymalny i minimalny element tablicy - wątki
KL
  • Rejestracja:ponad 6 lat
  • Ostatnio:ponad 4 lata
  • Postów:22
0

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.

S9
  • Rejestracja:ponad 10 lat
  • Ostatnio:5 miesięcy
  • Lokalizacja:Warszawa
  • Postów:3573
1

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ł.


"w haśle <młody dynamiczny zespół> nie chodzi o to ile masz lat tylko jak często zmienia się skład"
Shalom
  • Rejestracja:około 21 lat
  • Ostatnio:prawie 3 lata
  • Lokalizacja:Space: the final frontier
  • Postów:26433
1

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.


"Nie brookliński most, ale przemienić w jasny, nowy dzień najsmutniejszą noc - to jest dopiero coś!"
KL
  • Rejestracja:ponad 6 lat
  • Ostatnio:ponad 4 lata
  • Postów:22
0
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.

S9
  • Rejestracja:ponad 10 lat
  • Ostatnio:5 miesięcy
  • Lokalizacja:Warszawa
  • Postów:3573
1

@klonstoper:
Robisz jakąs klase MinMax która zwiera parę minimalnej i maksymalnej wartości i robisz klase

Kopiuj
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)


"w haśle <młody dynamiczny zespół> nie chodzi o to ile masz lat tylko jak często zmienia się skład"
edytowany 2x, ostatnio: scibi92
YA
  • Rejestracja:prawie 10 lat
  • Ostatnio:około 3 godziny
  • Postów:2368
0

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 ;-)

Henryk VIII Tudor
Henryk VIII Tudor
  • Rejestracja:prawie 5 lat
  • Ostatnio:prawie 5 lat
  • Postów:10
0

Typowe zadania na ForkJoina, poczytaj o tym

S9
  • Rejestracja:ponad 10 lat
  • Ostatnio:5 miesięcy
  • Lokalizacja:Warszawa
  • Postów:3573
0

@Henryk VIII Tudor: no chyba nie bardzo. ForkJoin jest do rekursji i bardzije nadaje się np. do Merge Sort, a tu nie ma rekursji :)


"w haśle <młody dynamiczny zespół> nie chodzi o to ile masz lat tylko jak często zmienia się skład"
Henryk VIII Tudor
Henryk VIII Tudor
a co robisz w merge sorcie?tez dzielisz na mniejsze podtablice
damianem
  • Rejestracja:prawie 8 lat
  • Ostatnio:3 miesiące
  • Postów:205
0
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).

S9
  • Rejestracja:ponad 10 lat
  • Ostatnio:5 miesięcy
  • Lokalizacja:Warszawa
  • Postów:3573
0

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...


"w haśle <młody dynamiczny zespół> nie chodzi o to ile masz lat tylko jak często zmienia się skład"
AK
  • Rejestracja:ponad 6 lat
  • Ostatnio:7 dni
  • Postów:3561
0

Zauważyliście, ze kolega odpadł na zakrętach?


Bo C to najlepszy język, każdy uczeń ci to powie
S9
I co z tego? Koledzy coś napisali, ja napisałem że uważam to za rozwiązanie nie pasujące to problemu i tyle.
KL
  • Rejestracja:ponad 6 lat
  • Ostatnio:ponad 4 lata
  • Postów:22
0

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:

Kopiuj
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);
    }
}
Kopiuj
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.

edytowany 3x, ostatnio: klonstoper
YA
  • Rejestracja:prawie 10 lat
  • Ostatnio:około 3 godziny
  • Postów:2368
0
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?
edytowany 1x, ostatnio: yarel
KL
  • Rejestracja:ponad 6 lat
  • Ostatnio:ponad 4 lata
  • Postów:22
0
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)

edytowany 1x, ostatnio: klonstoper
YA
  • Rejestracja:prawie 10 lat
  • Ostatnio:około 3 godziny
  • Postów:2368
1

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.

KL
  • Rejestracja:ponad 6 lat
  • Ostatnio:ponad 4 lata
  • Postów:22
0
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?

edytowany 1x, ostatnio: klonstoper
YA
  • Rejestracja:prawie 10 lat
  • Ostatnio:około 3 godziny
  • Postów:2368
0
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.

KL
  • Rejestracja:ponad 6 lat
  • Ostatnio:ponad 4 lata
  • Postów:22
0
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.

Henryk VIII Tudor
Henryk VIII Tudor
  • Rejestracja:prawie 5 lat
  • Ostatnio:prawie 5 lat
  • Postów:10
1

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ć).

Kopiuj

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);
    }
}
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)