Czy ktoś może mi zasugerować, jak mogę przekazać parametr do wątku?
Jak to działa w przypadku anonimowych zajęć?
java
multithreading
Steve
źródło
źródło
Consumer<T>
.Odpowiedzi:
Musisz przekazać parametr w konstruktorze do obiektu Runnable:
i wywołaj to w ten sposób:
źródło
r
będzie miał ten sam argument, więc jeśli chcemy przekazać różne argumenty do wielu działających wątkówMyThread
, musimy utworzyć nowąMyThread
instancję, używając żądanego argumentu dla każdego wątku. Innymi słowy, aby uruchomić wątek, musimy utworzyć dwa obiekty: Thread i MyThread. Czy jest to uważane za złe pod względem wydajności?Dla klas anonimowych:
W odpowiedzi na edycję pytania o to, jak to działa dla klas Anonimowych
Nazwane klasy:
Masz klasę, która rozszerza wątek (lub implementuje Runnable) oraz konstruktor o parametrach, które chcesz przekazać. Następnie, gdy tworzysz nowy wątek, musisz przekazać argumenty, a następnie rozpocząć wątek, mniej więcej tak:
Runnable jest znacznie lepszym rozwiązaniem niż Thread BTW. Wolałbym więc:
Ta odpowiedź jest w zasadzie taka sama jak w przypadku podobnego pytania: Jak przekazać parametry do obiektu Thread
źródło
parameter
bezpośrednio zrun()
metody bez użycia pola jakp
w ogóle. Wydaje się, że działa. Czy brakuje mi subtelnej wielowątkowości,parameter
którejp
wcześniej nie kopiowałem ?)
ci pierwszego przykładufinal X parameter
przednew Runnable()
linią, miałem dostęp doparameter
środkarun()
. Nie musiałem robić dodatkowych rzeczyp = parameter
.final
nie jest już tak ważny; wystarczy, jeśli zmienna jest faktycznie ostateczna (mimo że nie szkodzi jej posiadanie)za pomocą konstruktora klasy Runnable lub Thread
źródło
@Override
za?@Override
wyraźnie stwierdza, że zastępuje metodę abstrakcyjną w klasie Thread.Ta odpowiedź przychodzi bardzo późno, ale może ktoś uzna ją za przydatną. Chodzi o to, jak przekazać parametr (y) do
Runnable
nawet bez deklarowania nazwanej klasy (przydatne dla wkładek):Oczywiście możesz przełożyć wykonanie
start
na bardziej dogodny lub odpowiedni moment. I to od Ciebie zależy, jaki będzie podpisinit
metody (może więc wymagać więcej i / lub różnych argumentów) i oczywiście nawet jej nazwy, ale w zasadzie masz pomysł.W rzeczywistości istnieje również inny sposób przekazania parametru do anonimowej klasy za pomocą bloków inicjalizujących. Rozważ to:
Wszystko dzieje się więc w bloku inicjalizacyjnym.
źródło
this.myParam
wtedy naprawdę jest to konieczne? Czy nie można po prostu porzucić zmiennych prywatnych i odwołać się do zmiennej z zakresu zewnętrznego? Rozumiem (oczywiście), że ma to pewne implikacje, takie jak że zmienna jest otwarta na zmianę po uruchomieniu wątku.Podczas tworzenia wątku potrzebujesz wystąpienia
Runnable
. Najprostszym sposobem na przekazanie parametru byłoby przekazanie go jako argumentu do konstruktora:Jeśli następnie chcesz zmienić parametr podczas działania wątku, możesz po prostu dodać metodę ustawiającą do klasy uruchamialnej:
Gdy to zrobisz, możesz zmienić wartość parametru, wywołując w ten sposób:
Oczywiście, jeśli chcesz wywołać akcję po zmianie parametru, będziesz musiał użyć blokad, co znacznie komplikuje sytuację.
źródło
Aby utworzyć wątek, zwykle tworzysz własną implementację Runnable. Przekaż parametry do wątku w konstruktorze tej klasy.
źródło
Możesz rozszerzyć lub i podać parametry, jak chcesz. Istnieją proste przykłady w docs . Przeniesię je tutaj:
Thread
class
Runnable
class
źródło
Napisz klasę, która implementuje Runnable, i przekaż wszystko, czego potrzebujesz w odpowiednio zdefiniowanym konstruktorze, lub napisz klasę, która rozszerza Thread o odpowiednio zdefiniowanym konstruktorze, który wywołuje super () z odpowiednimi parametrami.
źródło
Począwszy od Java 8, możesz użyć lambda do przechwytywania parametrów, które są faktycznie ostateczne . Na przykład:
źródło
W Javie 8 możesz używać
lambda
wyrażeń z interfejsem API współbieżności iExecutorService
jako zamiennik wyższego poziomu do bezpośredniej pracy z wątkami:Zobacz także
executors
javadocs .źródło
Wiem, że jestem spóźniony o kilka lat, ale natknąłem się na ten problem i podjąłem niekonwencjonalne podejście. Chciałem to zrobić bez tworzenia nowej klasy, więc oto co wymyśliłem:
źródło
Przekazywanie parametrów za pomocą metod start () i run ():
źródło
Możesz wyprowadzić klasę z Runnable, a podczas budowy (powiedzmy) przekaż parametr w.
Następnie uruchom go za pomocą Thread.start (Runnable r);
Jeśli masz na myśli, gdy wątek jest uruchomiony, po prostu trzymaj odwołanie do swojego obiektu pochodnego w wątku wywołującym i wywołaj odpowiednie metody ustawiające (synchronizując w razie potrzeby)
źródło
Istnieje prosty sposób przekazywania parametrów do programów runnables. Kod:
źródło
Nie, nie możesz przekazać parametrów do
run()
metody. Podpis mówi ci to (nie ma parametrów). Prawdopodobnie najłatwiejszym sposobem na to byłoby użycie specjalnie zbudowanego obiektu, który pobiera parametr w konstruktorze i przechowuje go w zmiennej końcowej:Gdy to zrobisz - musisz uważać na integralność danych obiektu, który przekazujesz do „WorkingTask”. Dane będą teraz istnieć w dwóch różnych wątkach, więc musisz upewnić się, że są bezpieczne.
źródło
Jeszcze jedna opcja; takie podejście pozwala używać elementu Runnable jako asynchronicznego wywołania funkcji. Jeśli twoje zadanie nie musi zwracać wyniku, np. Wykonuje tylko pewną czynność, nie musisz się martwić o to, jak przekazać „wynik”.
Ten wzór pozwala ponownie użyć przedmiotu, w którym potrzebujesz pewnego rodzaju stanu wewnętrznego. Gdy parametry nie są przekazywane do konstruktora, należy zachować ostrożność, aby pośredniczyć w dostępie programów do parametrów. Możesz potrzebować więcej kontroli, jeśli twój przypadek użycia dotyczy różnych rozmówców itp.
}
Wątek t = nowy wątek (nowy MyRunnable (parametr)); t.start ();
Jeśli potrzebujesz wyniku przetwarzania, będziesz także musiał skoordynować ukończenie MyRunnable po zakończeniu zadania cząstkowego. Możesz oddzwonić lub poczekać na Wątek „t” itp.
źródło
Specjalnie dla Androida
Dla celów oddzwaniania zwykle implementuję swój własny rodzajowy
Runnable
z parametrami wejściowymi:Użycie jest proste:
W menedżerze:
źródło
Utwórz zmienną lokalną w swojej klasie, która
extends Thread
lubimplements Runnable
.W ten sposób możesz przekazać zmienną po uruchomieniu.
Wyjście:
źródło