Thread-Safe List v jave

xavier

Thread-Safe List v jave
« kdy: 03. 06. 2018, 16:26:00 »
Ahojte, potrebujem v projekte pouzit thread-safe mapu, ktorej typ hodnoty bude List.

Citace
Map<String, List<FooObject>> map = new ConcurrentHashMap<>();

Aku implementaciu listu by ste mi poradili? Nieco z guavy, alebo apache commons? Dik


Re:Thread-Safe List v jave
« Odpověď #1 kdy: 03. 06. 2018, 16:48:00 »
Proč nechcete použít některou z implementací ve standardní knihovně? A počítáte s tím, že použití thread-safe listu v thread-safe mapě ještě automaticky nezaručuje thread-safe použití jako celku?

Sten

Re:Thread-Safe List v jave
« Odpověď #2 kdy: 03. 06. 2018, 16:57:25 »
Doporučil bych standardní ConcurrentHashMap<K, CopyOnWriteArrayList<V>> nebo ConcurrentHashMap<K, ConcurrentLinkedQueue<V>>

Ale pozor, je to sice thread-safe (tzn. má to vždy definovaný výsledek při jakémkoliv konkurentním přístupu), ale výsledky mohou být odlišné, než budete čekat, třeba konkurentní put do té mapy se stejným klíčem vloží jen poslední vkládaný seznam, budete muset používat putIfAbsent a kontrolovat návratovou hodnotu. Bezpečná by byla konkurentní multimapa, ale neznám žádnou open source implementaci.

borekz

  • ****
  • 486
    • Zobrazit profil
    • E-mail
Re:Thread-Safe List v jave
« Odpověď #3 kdy: 03. 06. 2018, 17:05:35 »
To bude jeden producer a n consumerů ?
V případě více producerů stejně musíte synchronizovat vytvoření toho listu, pokud ještě v mapě není.
V tom ohledu je boží std::map v C++, protože při použití operátoru [] automaticky vytvoří nový objekt.
Stačí definovat map<vector> mapa; a můžete jednoduše přidávat prvky jedním příkazem mapa[klíč] += prvek;
Resp. místo map a vector nějakou thread safe variantu.

xavier

Re:Thread-Safe List v jave
« Odpověď #4 kdy: 03. 06. 2018, 17:28:33 »
Proč nechcete použít některou z implementací ve standardní knihovně? A počítáte s tím, že použití thread-safe listu v thread-safe mapě ještě automaticky nezaručuje thread-safe použití jako celku?

Nevyhybam sa ani tomu, kludne si necham poradit s multithreadingom nemam velke skusenosti.


xavier

Re:Thread-Safe List v jave
« Odpověď #5 kdy: 03. 06. 2018, 17:29:07 »
To bude jeden producer a n consumerů ?
V případě více producerů stejně musíte synchronizovat vytvoření toho listu, pokud ještě v mapě není.
V tom ohledu je boží std::map v C++, protože při použití operátoru [] automaticky vytvoří nový objekt.
Stačí definovat map<vector> mapa; a můžete jednoduše přidávat prvky jedním příkazem mapa[klíč] += prvek;
Resp. místo map a vector nějakou thread safe variantu.

Ano, bude viac producentov

Re:Thread-Safe List v jave
« Odpověď #6 kdy: 03. 06. 2018, 17:54:32 »
Kterou konkrétní implementaci vybrat záleží na tom, jakým způsobem se bude s daty pracovat. Pokud se bude z listu často paralelně číst, a jenom výjimečně do něj zapisovat, hodí se CopyOnWriteArrayList. Pokud se do listu bude běžně zapisovat, je lepší použít ConcurrentLinkedQueue nebo ConcurrentLinkedDequeue.

Celou mapu byste pak měl zapouzdřit do vlastního objektu, který bude mít např. metodu pro přidání položky a interně zavolá computeIfAbsent pro vytvoření listu, pokud ještě neexistuje, a pak do listu přidá hodnotu. Pokud je cílem multimapa, tj. mapa, která může mít pro jeden klíč víc hodnot, a stačí tedy tento slabší přístup k zamykání. Pokud by byl potřeba výhradní přístup k dané dvojici klíč:seznam, bylo by potřeba použít metodu compute.

xavier

Re:Thread-Safe List v jave
« Odpověď #7 kdy: 03. 06. 2018, 18:17:11 »
Citace
Celou mapu byste pak měl zapouzdřit do vlastního objektu, který bude mít např. metodu pro přidání položky a interně zavolá computeIfAbsent pro vytvoření listu, pokud ještě neexistuje, a pak do listu přidá hodnotu.

Nemozem uz priamove volat computeIfAbsent ja v danej triede namiesto obalovania dalsim objektom?

Citace
Kterou konkrétní implementaci vybrat záleží na tom, jakým způsobem se bude s daty pracovat.

S datami sa bude pracovat nasledovne:
Uzivatel A spusti aplikaciu, cim sa vytvori zaznam, kde key bude nejake id uzivatela, a nejake metada sa ulozia do Listu. Problem vsak je, ak otvori danu aplikaciu ten isty uzivatel na novej karte, v novom okne, casom mozno pribudne iny typ aplikacie, takze uzivatel bude prihlaseny na viacerych miestach naraz, co opat vyvola ulozenie metadat na zaklade id uzivatela do mapy. Preto metadata treba ukladat do kolekcie.

Taktiez moze nastat situacia, kedy uzivatel B, spusti nejaku akciu, ktora potrebuje metada uzivatela A, ta akcia pouzije vsetky metada priradene ku klucu uzivatela A, v iteracii nad kazdym zaznamom vykona nejaku operaciu, a nasledne sa z mapy odmaze kluc aj s metadatami uzivatela A.

Trosku som sa vam pokusil objasnit pre aku pracu potrebujem dany List, je pre tento pripad vhodny spominany CopyOnWriteArrayList alebo siahnut po niecom inom ?

Re:Thread-Safe List v jave
« Odpověď #8 kdy: 03. 06. 2018, 18:40:22 »
Nemozem uz priamove volat computeIfAbsent ja v danej triede namiesto obalovania dalsim objektom?
Můžete, ale pak musíte zajistit, že se prvky do mapy budou vkládat vždy správným voláním computeIfAbsent, nikdo nikdy nezavolá třeba put nebo jinou metodu pro přidání prvku do mapy. Než to hlídat na všech místech, kde by se to mohlo použít, je lepší tu mapu zapouzdřit do vlastního objektu, ze kterého se vystaví jenom metoda pro přidání hodnoty do mapy, a ta metoda už si sama zajistí, aby to přidání proběhlo správně. To je přesně důvod, proč se používá OOP.

S datami sa bude pracovat nasledovne:
Uzivatel A spusti aplikaciu, cim sa vytvori zaznam, kde key bude nejake id uzivatela, a nejake metada sa ulozia do Listu. Problem vsak je, ak otvori danu aplikaciu ten isty uzivatel na novej karte, v novom okne, casom mozno pribudne iny typ aplikacie, takze uzivatel bude prihlaseny na viacerych miestach naraz, co opat vyvola ulozenie metadat na zaklade id uzivatela do mapy. Preto metadata treba ukladat do kolekcie.

Taktiez moze nastat situacia, kedy uzivatel B, spusti nejaku akciu, ktora potrebuje metada uzivatela A, ta akcia pouzije vsetky metada priradene ku klucu uzivatela A, v iteracii nad kazdym zaznamom vykona nejaku operaciu, a nasledne sa z mapy odmaze kluc aj s metadatami uzivatela A.
Používat na tohle list mi tedy připadá dost divoké. Spíš bych do té mapy dával vlastní objekt představující přihlášeného uživatele, který bude poskytovat vlastní služby – vyhledání metadat pro danou aplikaci, odhlášení od aplikace apod. Protože třeba to procházení listu není atomická operace, a když k tomu budete přistupovat z více vláken, může se vám stát, že z jednoho vlákna ten prvek z listu smažete, ale v druhém vlákně ten prvek třeba budete modifikovat. List se tím nepoškodí a nakonec z něj ten prvek bude smazán, ale je otázka, zda je správné chování aplikace, která jeden záznam zároveň mění i maže.

Trosku som sa vam pokusil objasnit pre aku pracu potrebujem dany List, je pre tento pripad vhodny spominany CopyOnWriteArrayList alebo siahnut po niecom inom ?
To pořád závisí na poměru počtu zápisů k počtu čtení těch listů a třeba také na jejich velikosti. Což z toho vašeho popisu není patrné. Ale podle toho, jak jste to popsal, bych tam vůbec nedával list.

xavier

Re:Thread-Safe List v jave
« Odpověď #9 kdy: 03. 06. 2018, 18:51:27 »
Citace
To pořád závisí na poměru počtu zápisů k počtu čtení těch listů a třeba také na jejich velikosti. Což z toho vašeho popisu není patrné. Ale podle toho, jak jste to popsal, bych tam vůbec nedával list.

Pocet zapisov by nemal byt velky, teda kazdemu klucu bude priradeny 1 zaznam, no ako som spominal problem je, ak uzivatel otvori aplikaciu v novej karte, alebo okne. Vtedy pod dany kluc v mape pribudne novy zaznam. Bohuzial nemam napad ako to spravit inac. Data ulozene v liste maju predstavuju asynchronne requesty uzivatelskych aplikacii, teda tymto ulozenym requestom sa nastavuje response, a nasledne je vystup vrateny aplikacii.

Re:Thread-Safe List v jave
« Odpověď #10 kdy: 03. 06. 2018, 19:19:27 »
Rovněž doporučuji v první řadě zapouzdřit na úrovni "musí to umět operace X, Y, Z". To vám umožní vyzkoušet různé implementace.

xavier

Re:Thread-Safe List v jave
« Odpověď #11 kdy: 03. 06. 2018, 19:32:22 »
Rovněž doporučuji v první řadě zapouzdřit na úrovni "musí to umět operace X, Y, Z". To vám umožní vyzkoušet různé implementace.

ano, zapuzdrenie urcite zvazim, ale aj tak sa zrejme nevyhnem pouzitiu nejakeho Listu

Re:Thread-Safe List v jave
« Odpověď #12 kdy: 03. 06. 2018, 20:43:07 »
Data ulozene v liste maju predstavuju asynchronne requesty uzivatelskych aplikacii, teda tymto ulozenym requestom sa nastavuje response, a nasledne je vystup vrateny aplikacii.
Pořád nechápu, proč by ty requesty měly být uložené zrovna v listu. Co s těmi requesty budete dělat? Jak vznikne response k danému requestu?

xavier

Re:Thread-Safe List v jave
« Odpověď #13 kdy: 03. 06. 2018, 20:57:00 »
Data ulozene v liste maju predstavuju asynchronne requesty uzivatelskych aplikacii, teda tymto ulozenym requestom sa nastavuje response, a nasledne je vystup vrateny aplikacii.
Pořád nechápu, proč by ty requesty měly být uložené zrovna v listu. Co s těmi requesty budete dělat? Jak vznikne response k danému requestu?

Vyuziva sa trieda zo springu deferred result, ktora zabezpeci to, aby dany objekt bol vrateny ako response az ked sa mu nastavi result. Tym ze tieto objekty drzim v kolekcii, mozem im nastavit result kedy to je potrebne, a vtedy je vysledok vrateny uzivatelovi.

Re:Thread-Safe List v jave
« Odpověď #14 kdy: 03. 06. 2018, 21:05:45 »
Vyuziva sa trieda zo springu deferred result, ktora zabezpeci to, aby dany objekt bol vrateny ako response az ked sa mu nastavi result. Tym ze tieto objekty drzim v kolekcii, mozem im nastavit result kedy to je potrebne, a vtedy je vysledok vrateny uzivatelovi.
To ale pořád není důvod držet requesty v kolekci. Přece nějak zjistíte, že máte co uživateli vrátit – buď na to čekáte, tak můžete mít ten deferred result uložený u toho čekání, nebo ty odpovědi chodí nějak úplně nezávisle (např. na chatu – „pošli zprávu uživateli XY“), ovšem pak zase musíte umět identifikovat, kam se má poslat ta odpověď, a hodila by se spíš mapa, kde by byl klíč ten identifikátor a hodnota ten response. Netvrdím, že nemůže být případ, kde je vhodné použít list, ale nic moc takového mne nenapadá. Snad jen kdybyste chtěl uživateli zobrazit frontu jeho požadavků, jak postupně přicházely, nebo chtěl postupně v pořadí zpracovat všechny požadavky uživatele. Ale to neodpovídá tomu deferred result.