Thread safe collection czy concurrent dla takich samych kluczy w każdym wątku + sortowanie

0

Mam List<List<File>>, która dziele i dla każdej części odpalam n Threads. Każdy Thread buduję TreeMap<String, List<String>>. Chcę później połączyć te wszystkie mapy w jednąTreeMap<String, List<String>> (ale mogą zawierać one ten sam klucz w innym wątku, tzn. jakieś porównania muszą zostać wykonane) albo chciałbym użyć jakiejś threa-safe collection czy concurent, ale nie wiem, której? Klucz może być taki sam dla każdej TreeMap<String, List<String>> ("zwróconej przez Thread"), ale musi być posortowany w głownej TreeMapie, a wartości pojedynczych TreeMaps muszą zostać połączone. Pytanie czy lepiej to połączyć w całość czy uzyć jakiejś thread-safe collection albo concurrent? I jeśli tak to czego?

List<File> filesAndFoldersList = Arrays.asList(filesAndFoldersArray);

        List<List<File>> filesArrays = divideArrayIntoChunks(filesAndFoldersList, 100);
        

        for (int i = 0; i < filesArrays.size(); i++) {

            List<File> filesList = filesArrays.get(i);

            BuildNamesAndFileNamesMap buildNamesAndFileNamesMap = new BuildNamesAndFileNamesMap(... , i);

            Thread thread = new Thread(buildNamesAndFileNamesMap, "Thread " + i);
            thread.start();

            if (buildNamesAndFileNamesMap.hasFinished()) {

                namesAndFileNamesPartMap = buildNamesAndFileNamesMap.getNamesAndFileNamesMap();
                ... // join to main TreeMap or?
            }
            
        }

To jest klasa BuildNamesAndFileNamesMap:

private static class BuildNamesAndFileNamesMap implements Runnable {

        ....
        private final TreeMap<String, List<String>> namesAndFileNamesMap;
        private int threadNumber;

        private boolean hasFinished = false;

        public BuildNamesAndFileNameMap(..., int threadNumber) {

            ...// tworzona jest nowa kolekcja namesAndFileNamesMap
        }

        public TreeMap<String, List<String>> getNamesAndFileNamesMap() {
            return namesAndFileNamesMap;
        }

        public boolean hasFinished() {
            return hasFinished;
        }

        @Override
        public void run() {

            ...// do some stuff

            namesAndFileNamesMap.put(...);
            hasFinished = true;
        }
    }
2
 Thread thread = new Thread(buildNamesAndFileNamesMap, "Thread " + i);
            thread.start();

To jest złe, tak się nie robi. Słyszałeś o ExecutService?

  1. To wygląda na jakis problem XY, co ty w ogóle chcesz zrobić?
    Czy Ty modyfikujesz te dane przekazane w kolekcji?
0
  1. Co jest w tym złego? Bez szczegółów to każdy może coś takiego napisać.
    Jeśli chodzi ci o maksymalną ilość wątków to jest ok.
  2. Niczego nie modyfikuję, buduję nową kolekcję.

BuildNamesAndFileNamesMap tworzy nową kolekcję zupełnie inną i niczego nie modfikuję. Pytanie w temacie jest zupełnie inne.

1
  1. To że używa się pól wątków. Każdy wątek zajmuje pamięć i masz poza tym ograniczoną liczbę rdzeni, puszczanie setek wątków może nie mieć sensu po prostu. A jak masz ExecutService to masz pulę wątkow i kolejkę do obsługi zadań, kończysz 1, bierzesz drugie.
    2)Jeśli nie modyfikujesz listy tylko tworzysz nową nie potrzebujesz jakiś fancy threadsafe kolekcji. Nie potrzebujesz tez podziału na mniejsze kolekcje, jak masz Listę 100 elementów, wątek A bierze pierwsze 50, drugi kolejne 50 i gra i buczy,
    3)Nie odpowiedzialeś co ta aplikacja ma zrobić? pobrać nazwy plików dla folderów?
0
  1. Dzielę bo tworzę zupełnie inną kolekcję. Z imionami i nazwiskami dopasowanymi jako klucz i listą nazw plików jako values. Imion i nazwisk jest ok 20 tys. A na jednym wątku, dopasowanie 1000 nazw plików, trwa ok 20 minut. Dopasowanie robię kilkoma algorytmami. Z czego najbardziej czasochłonny jest ten, który zawiera equals == true, dla dwóch stringów różniących się o jeden element.
  2. Aplikacja ma sortować pliki po imionach i nazwiskach, o ile dopasuje. Nazwy plików mogą zawierać imiona i nazwiska napisane z błędami.
0
zgrzyt napisał(a):

Aplikacja ma sortować pliki po imionach i nazwiskach, o ile dopasuje. Nazwy plików mogą zawierać imiona i nazwiska napisane z błędami.

Ale ma to zrobić raz na wieki wieków i pozdro? Czy ma to robić cyklicznie? Bo jeśli nie jest to jednorazowa akcja, to dane do posortowania co jakiś czas przychodzą, czyli coś jest inputem. No i właśnie - co jest inputem? Nazwa pliku? I wtedy potrzebujemy jednego pliku i wszystkich nazwisk z nim związanych? Co potem z tymi posortowanymi danymi? Gdzieś je wysyłasz / zapisujesz / wyświetlasz? Myślę że szerszy kontekst faktycznie pomoże, i być może problemy wielowątkowości nagle faktycznie znikną, tak jak mówił @scibi92 o XY problemie.

Ja wiem, że ciężko jest teraz Tobie zrobić krok wstecz i popatrzeć na to jakby "z boku", bo już się zaangażowałeś w dane rozwiązanie i będziesz chciał się go trzymać. Ale myślę że taki krok wstecz by pomógł.

0

Moze to robic wielorazowo, ale tylko wtedy gdy zostanie uruchomiona i wyklucza pliki, ktore zostaly juz posortowane. Oczywiscie kolejna operacja nie zacznie sie dopoki wczesniejsza nie zostanie ukonczona.
Poczatkowym inputem jest nazwa pliku, a wlasciwie to File. No i oczywiscie imiona i nazwiska. Posortowane pliki trafiaja do folderow nazwanych imionami i nazwiskami. O ile ich nazwa zostala dopasowana do imienia i nazwiska. Algorytm wydaje sie byc dobry, poza tym, ze czasochlonne jest szukanie bledow w nazwach plikow, jezeli np. w nazwie pliku bedzie .... Jose Manual Eduardo ...., zamiast Jose Manuel Eduardo.

0

@zgrzyt:

Aplikacja ma sortować pliki po imionach i nazwiskach, o ile dopasuje. Nazwy plików mogą zawierać imiona i nazwiska napisane z błędami.

  1. Jak wygląda nazwa pliku? Zawsze jest to imię, nazwisko, czy może to być np. dowolny text+imię z błędami + dowolny tekst + nazwisko z błędami ?

  2. zakładając, że Hanna Kowalska, Anna Kowalska to dane referencyjne (z tych ok. 20 tys), to:
    a) co zwraca dopasowanie dla Zuzanna Kowalska?
    b) czy dopasowanie jest tylko 1 czy może być wiele? (np. Hanna -> Anna, Hanna) ?

  3. Rozważałeś inne podejście? np. uczenie maszynowe i "dopasowanie" wystarczająco "dobre"?

0

Okej, a po tym pierwszym wykonaniu, w jakim tempie będą przychodzić kolejne pliki? Bo z tego co mi się w tej chwili wydaje, to być może czasochłonne będzie to zrobienie pierwszy raz, a potem, jeśli tych danych będzie już mało, to pójdzie już szybko?

0
  1. Tak nazwa pliku moze zawierac dowolnie umieszczone teksty. To zostało zaimplementowane.
  2. Zostanie dopasowana Hanna Kowalska do Hanna Kowalska, algorytm porownuje liczbe dopasowanych liter.
    a). Zuzanna Kowalska.
    b). Dopasowanie moze byc tylko jedno, albo zadne.
  3. Nie znam innego podejscia. Moja wiedza programistyczna nie jest na tyle duza.
0
Pinek napisał(a):

Okej, a po tym pierwszym wykonaniu, w jakim tempie będą przychodzić kolejne pliki? Bo z tego co mi się w tej chwili wydaje, to być może czasochłonne będzie to zrobienie pierwszy raz, a potem, jeśli tych danych będzie już mało, to pójdzie już szybko?

Problemem nie są przychodzące pliki problem jest tylko jak każdy Thread się uruchomi i ma zbudować mapę imię i nazwisko => nazwy plików. Mapy mogą zawierać te same imiona i nazwiska i pytanie tylko jaka kolekcje lub konkurent wykorzystać żeby to później posortować ładnie i szybko w java.collections albo automatycznie o ile to możliwe w java.concurrent?

0

Nie rozumiem treści zadania :( dlaczego to są TreeMapy? Co ma być posortowane? Podaj jakiś przykład dla ułomnych.

Pytanie czy ostatecznego scalenia nie zrobić już w jednym wątku, skoro wszystko masz posortowane po pierwszej fazie?

EDIT: gdyby tak się dało to można by pokusić się o scalenie używając ForkJoinPool, każdy task bierze 2 mapy i scala je w jedną większą do momentu aż pozostanie jedna mapa. Tylko wcale nie jest powiedziane, że to będzie dużo szybsze, nie wiem ile jest elementów i w jaki czas celujesz.

0

Tak, sortowanie w jednym watku. Mi chodzi wlasnie o to, ktore rozwiazanie bedzie szybsze? Zapisanie do wielu HashMap, odczyt sortowanie i zmergowanie czy np. bez mergowania zapis do ConcurentHashMap, ConcurrentSkipListMap i posortowanie? To co tutaj jest to pseudokod.

4

Opisujesz swoje rozwiązanie w niejasny sposób. Nie wiem jak chcesz posortować HashMapę. Odnośnie szybkości, to nie wiadomo, trzeba by zmierzyć. Więcej wątków nie zawsze znaczy szybciej. Być może nie potrzebujesz tego aż tak żyłować i lepiej skupić się na czytelności.

0

Twoja wypowiedź jest na zasadzie nie wiem to się wypowiem :)

1

@zgrzyt: a tak swoją drogą, to weź pod uwage to że pewno to zadanie o którym piszesz nie jest jedynym wykonywanym w tej aplikacji/serwerze.
Jeśli jest to częś aplikacji to może powodować głodzenie wątków - załóżmy że możesz odpalić 16 wątków i wszystkie wątki zajmie ten feature, każdy wątek potrwa po 5 minut. To znaczy że instancja będzie niedostępna na 5 minut na requesty HTTP itp.
Nawet jeśli to aplikacja celowa która ma sortowac to uwzględnij że potencjalnie mogą korzystać z tego serwera(choć teraz się robi 1 aplikacja/1 serwer zdaje się) -tl;dr; - zadbaj o odpowiednią wielkość puli wątków
PS
Przeczytałeś już co do ExecutorService?

0

Właśnie jest jedynym, aplikacja nie przyjmuje żadnych requestów. Mam pewne podstawy wiedzy. Wypisywanie czegoś czego aplikacja nie robi nie ma tutaj sensu. Tak samo szukanie dziury w całym. Aplikacja działa na plikach lokalnych. Póki co implementuje CompletableFuture, ale nie osiągam jeszcze oczekiwanych rezultatów.

0

W innym wątku wkleiłem Ci rozwiązanie, chyba, że nie skumałem ocb. Sam wybór klasy jest wtórny, ważne jakie podejście/algorytm chcesz zaimplementować.

1 użytkowników online, w tym zalogowanych: 0, gości: 1