Aktywne Wpisy
dxy32 +649
Chrysopoeia +22
Jestem totalnie uzalezniony od czipsów albo coś w tym stylu. Mam 24 lata i od wielu lat (10+) nałogowo wpieprzam czipsy. Zaczęło się od tego, że gdy byłem już totalnie malutki to tata często kupował mi małe paczki czipsów bo już wtedy je uwielbiałem. Obecnie prawie codziennie jem dużą paczkę czipsów (130g). Zdarzają się takie dni gdy zjem więcej. Przykładowo dwa dni temu zjadłem 3 paczki jednego dnia, łącznie 320g. Próbowałem jakoś
@Override public void run(){
running = true;
while(running){
if(infected.size() > 0){ /* loop that reads People from list of Infected, and informs their contacts */
Person p = infected.removeFirst();
ArrayList contacts = database.getContactRecords().get(p);
for(Contact c: contacts) {
Person p2 = c.getPhone();
p2.notifiedAboutPositiveContact();
numberContactsNotified.getAndIncrement();
}
}
pause(100L);
}
}
Czy powinienem uzyc "synchronized(infected)" i dopiero robic to dalej? Czy jak watek zaczal swoja metode run() moze nastapic zmiana kontekstu czy run() zostanie wykonane i dopiero moze zastapic zmiana kontekstu?
#java #programowanie
Jeżeli przypisujesz referencję w konstruktorze:
this.infected = infected
to ten kod nie jest bezpieczny pod względem wielowątkowym ze względu na mutację kolekcji metodą removeFirst()
Możesz oczywiście zrobić blok synchronizacji ale to dosyć zawodne rozwiązanie, w każdym miejscu gdzie modyfikujesz listę musisz o tym pamiętać. Lepszym rozwiązaniem byłoby przekazywać już bezpieczną wątkowo implementację Listy do wątku, możesz to zrobić wrappując ją przy pomocy:
Wszystkie te metody(klasy Website) dzialaja na bezpiecznej watkowo liscie(Collections.snchronizedList(....)). Dodatkowo we wszystkich metodach operujacych na tej liscie blokuje ja uzywajac "synchronized(syncList){}).
Edit: w sumie skoro w konstruktorze tworze bezpieczna liste, to czy w run() moge
Jeżeli tak to czemu potrzebujesz wątku?
[*]
Przy pracy z nim (jak z większością bibliotek UI) najważniejsze jest żeby
- nie blokować głównego wątku, wszystko co może trwać więcej niż parę ms lepiej jest obsługiwać asynchronicznie. Może to być poprzez wykorzystanie CompletableFuture.runAsync / supplyAsync
- wszystko co tyka UI powinno być wykonywane z głównego wątku (struktury danych dla UI nie są bezpieczne wątkowo np drzewa elementów na widoku) możesz zmienić wątek wykonania poprzez:
SwingUtilities.invokeLater(...)
@cugowski: Ten kod będzie działał proaktywnie (co jakiś czas odświeżę wszystkie kontrolki...) , UI lepiej żeby działało reaktywnie (zmiana w modelu pociąga odświeżenie widoku, reaguję tylko na zmiany...)
Najważniejsze żeby oddzielić model od widoku, widok powinien być w jakiś sposób informowany o zmianach w modelu. Może to być Observable, EventListenery itp.
Dlaczego SwingUtilities.invokeLater(...) sprawiało problemy?
Jeżeli tak to obydwa źródła tych danych się są reaktywne tj. klient musi wysłać request HTTP lub klient musi wysłać zapytanie SQL żeby dostać nowe dane.
Najprostsze rozwiązanie to guzik Refresh który pobiera na żądanie te dane.
Twój Website (Model) może mieć metodę refreshInfected() która wysyła GETa i na podstawie rezultatu odświeża swój wewnętrzny stan
Kurde, szkoda, ze gdzies tego nie poruszylem, zaoszczedzilo by to mnostwo Twojego czasu, ktory poswieciles na ten post. Przepraszam kolego.
zmieni się tylko implementacja refreshInfected(), wzorzec zostaje ten sam
Podziwiam Twoja wiedze w temacie. Programujesz w javie na co dzien?
Dzieki za dzisiejsza pomoc kolego ;)