2010-09-19 11 views
5

Jestem zdezorientowany:
Aby używać wątków w programie Java, najprostszym sposobem jest rozszerzenie klasy Thread i implementowanie działającego interfejsu (lub po prostu wdrożenie działającego).
Aby rozpocząć wykonywanie wątku. musimy wywołać metodę Thread(), która z kolei wywołuje metodę run() wątku. I tak zaczyna się wątek.
Metoda start() (chyba że się mylę) musi zostać wywołana dokładnie i tylko raz dla każdego wątku. W rezultacie wystąpienia wątków nie mogą być ponownie użyte, chyba że sama metoda uruchamiania działa w nieskończonej pętli, co ułatwia niestandardową implementację ponownego wątku wątku.
Teraz javadoc link text mówiPonowne użycie wątku Java za pomocą executora

zwraca wykonać będzie ponownie użyć wcześniej skonstruowane wątki jeśli dostępne

ja nie rozumiem, jak to jest realizowane. Dostarczam w metodzie execute metody executora mój niestandardowy wątek np.

W jaki sposób ten niestandardowy wątek, który deleguję do struktury executorów, może być ponownie użyty?
Czy Executor może wywołać metodę start() więcej niż 1 raz, podczas gdy my nie możemy w naszych programach? Czy coś nie rozumiem?

Dziękuję.

Odpowiedz

4

Należy zauważyć, że nie jest to Executor, który wywołuje start() - jest to ExecutorService. I nie, to nie jest dwukrotne wywołanie start(). Nie uruchamia zadania, które dajesz bezpośrednio, używając Thread.start() ... zamiast tego uruchamia wątek, który wie o kolejce pracy puli wątków. Wątek będzie w zasadzie czekać, aż będzie trochę pracy, a następnie podnieś go i wykonaj, zanim wrócisz do czekania. Więc chociaż wątek wykonuje kilka zadań, Thread.start() jest wywoływany tylko raz.

EDYCJA: Sądząc po komentarzach, jesteś nieco zdezorientowany różnicą między Runnable (która jest zadaniem do wykonania) i Thread (co jest tym, co wykonuje zadania).

Ten sam wątek może wykonywać wiele zadań. Na bardzo prostym przykładzie nie przy użyciu puli wątków, rozważ to:

(Ignoruj ​​potencjalnych problemów związanych z bezpieczeństwem nić stosując List<T> z wielu wątków.)

Można by stworzyć całą masę Runnable zadań zdolne do robienia różnych rzeczy, a następnie stworzenia pojedynczego MultiRunnable, aby uruchomić je po kolei. Przekaż instancję MultiRunnable do konstruktora Thread, a następnie, po uruchomieniu wątku, wykona każde z oryginalnych uruchamianych zadań. To pomaga?

+0

@Jon: Przepraszam cię straciłem. Tak więc wewnętrzne wątki frameworka są ponownie wykorzystywane, a nie uruchamiane przeze mnie jako argument do wykonania? Mój wątek, który przekazuję do tej struktury, będzie ponownie tworzony za każdym razem, ale przez to samo wystąpienie wewnętrznego wątku tworzonego przez framework? – Cratylus

+0

@ user384706: Tak. Twój runnable * nie jest * wątkiem - to tylko zadanie do wykonania. Musisz rozróżnić te dwa; są bardzo różne. –

+0

@Jon: Dziękuję bardzo. Jedyne, czego nie jestem pewien, to jaka jest korzyść z używania Executors.newCachedThreadPool(); Ponieważ jeśli moja klasa implementująca działające (dla zadania) jest kosztowna do utworzenia, nie będzie ponownie używana i ten sam wątek struktury będzie nadal używać nowych instancji zadania. Więc co mogę zyskać z tego api? Chyba że koncepcja jest taka, że ​​każda klasa implementująca działające jest minimalna. – Cratylus

5

Nie wywołuje funkcji start() więcej niż jeden raz; zamiast tego wątek w basenie nigdy się nie kończy, ale po prostu pozostaje żywy - czeka. Kod źródłowy jest dostępny do pobrania, jeśli chcesz go obejrzeć.

Każdy wątek w puli wątków może po prostu wait() dla Executora, aby przekazał mu nowy Runnable, ale jego własna metoda run() nie została ukończona. Po prostu czeka na wykonanie Runnable dla Egzekutora.

+0

Masz na myśli to, że w javadoc, gdzie mówi "że wcześniej skonstruowane wątki będą ponownie wykorzystane" nie odnosi się to do działania, które przechodzę do wykonania, ale do wewnętrznych wątków struktury executorów? Więc mój Runnable zostanie ponownie utworzony przez ten sam wątek puli wątków? Czy rozumiem, co mówisz? – Cratylus

+2

Twój runnable nie zostanie przywrócony. Twoja uruchomiona instancja zostanie przydzielona jednemu z wątków w puli. Ten wątek ma swoją własną metodę 'run()', której nie można (nie może być) zastąpić przez metodę Runna (Runnable). Metoda run() wątku wywoła metodę 'Runnable'' run() ', a następnie po zakończeniu' Runnable.run() ', wątek w końcu (będzie trzeba przeprowadzić księgowość) wróć do 'wait'ing. – jbindel

1

Aby "uruchomić" wątek więcej niż raz, utwórz operację. Na przykład:

//NO 
private class T extends Thread { //not necessary to implement runnable 
    public void run(){ 
     //... 
    } 
} 
void someMethod(){ 
    T a = new T(); 
    a.start(); 
    a.start(); //NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO 
} 

Zamiast

//Yes 
private class T implements Runnable { 
    public void run(){ 
     //... 
    } 
} 
void someMethod(){ 
    T a = new T(); 
    new Thread(a).start(); 
    new Thread(a).start(); //YES YES YES 
} 

Jest również możliwe, aby to zrobić:

void someMethod(){ 
    final Runnable r = new Runnable(){ 
     public void run(){ 
      //... 
     } 
    }; 
    new Thread(r).start(); 
    new Thread(r).start(); 
} 
// r could also be a field of you class. 
Powiązane problemy