Różnica między interfejsami Runnable i Callable w Javie
492
Jaka jest różnica między używaniem interfejsów Runnablei Callablepodczas projektowania współbieżnego wątku w Javie, dlaczego miałbyś wybierać jeden z nich?
Interfejs wywoływalny jest podobny do Runnable, ponieważ oba są przeznaczone dla klas, których instancje są potencjalnie wykonywane przez inny wątek. Runnable jednak nie zwraca wyniku i nie może zgłosić sprawdzonego wyjątku.
Jaka jest potrzeba posiadania obu, jeśli Callablemoże zrobić wszystko, co Runnablerobi?
Ponieważ Runnableinterfejs nie może zrobić wszystkiego, co Callablerobi!
Runnableistnieje już od wersji Java 1.0, ale Callablezostał wprowadzony tylko w wersji Java 1.5 ... do obsługi przypadków użycia, które Runnablenie obsługują. Teoretycznie zespół Java mógł zmienić sygnaturę Runnable.run()metody, ale złamałoby to binarną kompatybilność z kodem wcześniejszym niż 1.5, wymagając ponownego przekodowania podczas migracji starego kodu Java do nowszych JVM. To DUŻY NIE-NIE. Java stara się być kompatybilna wstecz ... i to był jeden z największych punktów sprzedaży Java dla komputerów biznesowych.
Oczywiście są przypadki użycia, w których zadanie nie musi zwracać wyniku ani zgłaszać sprawdzonego wyjątku. W przypadku tych przypadków użycie Runnablejest bardziej zwięzłe niż użycie Callable<Void>i zwrócenie wartości dummy ( null) z call()metody.
Zastanawiam się, skąd masz tę historię. To jest bardzo przydatne.
Spider
4
@prash - podstawowe fakty można znaleźć w starych podręcznikach. Podobnie jak pierwsza edycja Java w pigułce.
Stephen C
4
(@prash - Także ... zaczynając używać Java w erze Java 1.1.)
Stephen C
1
@StephenC Jeśli poprawnie przeczytałem twoją odpowiedź, sugerujesz, że Runnableistnieje (w dużej mierze) ze względu na kompatybilność wsteczną. Ale czy nie są sytuacje, w których wdrożenie (lub wymaganie) Callableinterfejsu (np. W ScheduledFuture<?> ScheduledExecutorService.schedule(Runnable command, long delay, TimeUnit unit)) jest niepotrzebne lub zbyt drogie ? Czy zatem utrzymanie obu interfejsów w języku nie ma żadnej korzyści, nawet historia nie wymusiła obecnego wyniku?
maksymalnie
1
@max - Cóż, powiedziałem to i nadal się z tym zgadzam. Jest to jednak drugi powód. Ale mimo to podejrzewam, że Runnablezostałby zmodyfikowany, gdyby nie było konieczności zachowania zgodności. „Płyta kotła” return null;jest słabym argumentem. (Przynajmniej taka byłaby moja decyzja ... w hipotetycznym kontekście, w którym można zignorować wsteczną kompatybilność.)
Stephen C
81
CallableMusi wdrożyć call()metody natomiast Runnablemusi wdrożyć run()metody.
A Callablemoże zwrócić wartość, ale Runnablenie może.
CallableMoże rzucić wyjątek sprawdzone ale Runnablenie mogę.
CallableMoże być używany z ExecutorService#invokeXXX(Collection<? extends Callable<T>> tasks)metod, ale Runnablenie może być.
publicinterfaceRunnable{void run();}publicinterfaceCallable<V>{
V call()throwsException;}
ExecutorService.submit (zadanie Runnable) również istnieje i jest bardzo przydatne
Yair Kukielka
Runnable może być również używany z ExecutorService w następujący sposób: 1) ExecutorService.execute (Runnable) 2) ExecutorService.submit (Runnable)
Azam Khan
2
Istnieje również plik Executor.submit (zadanie na żądanie <T>), ale nie można wywoływać wszystkiego ani wywoływać dowolnego z kolekcją zadań Runnable Collection <? rozszerza zadania
wywoływalne
36
Znalazłem to na innym blogu, który może wyjaśnić nieco więcej tych różnic :
Chociaż oba interfejsy są implementowane przez klasy, które chcą wykonać w innym wątku wykonania, ale istnieje kilka różnic między tymi dwoma interfejsami, które są:
Callable<V>Instancji zwraca wynik typu V, podczas gdy Runnableinstancja nie.
Callable<V>Instancja może rzucać sprawdzonych wyjątków, natomiast Runnableinstancji nie może
Projektanci Java odczuli potrzebę rozszerzenia możliwości Runnableinterfejsu, ale nie chcieli wpływać na wykorzystanie Runnableinterfejsu i prawdopodobnie dlatego zdecydowali się na osobny interfejs o nazwie CallableJava 1.5, niż zmieniający już istniejących Runnable.
Przyjrzyjmy się, gdzie można użyć Runnable i Callable.
Zarówno Runnable, jak i Callable działają na innym wątku niż wątek wywołujący. Ale Callable może zwrócić wartość, a Runnable nie. Gdzie to naprawdę ma zastosowanie.
Runnable : Jeśli masz zadanie pożaru i zapomnienia, użyj Runnable. Umieść swój kod w Runnable, a po wywołaniu metody run () możesz wykonać swoje zadanie. Wątek wywołujący naprawdę nie ma znaczenia podczas wykonywania zadania.
Callable : Jeśli próbujesz odzyskać wartość z zadania, użyj Callable. Teraz samodzielne wywołanie nie zadziała. Będziesz potrzebować Przyszłości, którą obejmiesz na żądanie i uzyskasz wartości na future.get (). Tutaj wątek wywołujący zostanie zablokowany, aż Przyszłość powróci z wynikami, które z kolei czekają na wykonanie metody call () Callable.
Pomyśl więc o interfejsie do klasy docelowej, w którym zdefiniowano zarówno metody zawijalne Runnable, jak i Callable. Klasa wywołująca losowo wywołuje metody interfejsu, nie wiedząc, która jest Runnable, a która Callable. Metody Runnable będą wykonywane asynchronicznie, dopóki nie zostanie wywołana metoda Callable. Tutaj wątek klasy wywołującej zostanie zablokowany, ponieważ pobierasz wartości z klasy docelowej.
UWAGA: W klasie docelowej można wykonywać wywołania do wywoływania i uruchamiania na jednym executorze wątków, co czyni ten mechanizm podobny do szeregowej kolejki wysyłania. Tak długo, jak wywołujący wywoła metody opakowane w Runnable, wątek wywołujący będzie działał naprawdę szybko bez blokowania. Gdy tylko wywoła metodę Callable zawiniętą w metodę Future, będzie musiała blokować do momentu wykonania wszystkich pozostałych pozycji w kolejce. Dopiero wtedy metoda zwróci wartości. To jest mechanizm synchronizacji.
Callableinterfejs deklaruje call()metodę i należy podać ogólne, ponieważ typ wywołania obiektu () powinien zwrócić -
publicinterfaceCallable<V>{/**
* Computes a result, or throws an exception if unable to do so.
*
* @return computed result
* @throws Exception if unable to compute a result
*/
V call()throwsException;}
Runnablez drugiej strony jest interfejs, który deklaruje run()metodę, która jest wywoływana podczas tworzenia wątku z runnable i wywołuje na nim start (). Możesz także bezpośrednio wywołać run (), ale to po prostu uruchamia metodę run () w tym samym wątku.
publicinterfaceRunnable{/**
* When an object implementing interface <code>Runnable</code> is used
* to create a thread, starting the thread causes the object's
* <code>run</code> method to be called in that separately executing
* thread.
* <p>
* The general contract of the method <code>run</code> is that it may
* take any action whatsoever.
*
* @see java.lang.Thread#run()
*/publicabstractvoid run();}
Podsumowując kilka znaczących różnic
RunnableObiekt nie zwraca wynik podczas gdy Callableobiekt zwraca wynik.
RunnableObiekt nie może rzucać sprawdzonej wyjątek ubezpieczeniowy Callableobiekt może rzucić wyjątek.
RunnableInterfejs istnieje od Java 1.0 natomiast Callablezostał wprowadzony dopiero w Javie 1.5.
Kilka podobieństw obejmuje
Wystąpienia klas implementujących interfejsy Runnable lub Callable są potencjalnie wykonywane przez inny wątek.
Wystąpienie interfejsów wywoływalnych i uruchamialnych może być wykonane przez ExecutorService metodą subm ().
Oba są interfejsami funkcjonalnymi i mogą być używane w wyrażeniach Lambda od Java8.
Metody w interfejsie ExecutorService są
<T>Future<T> submit(Callable<T> task);Future<?> submit(Runnable task);<T>Future<T> submit(Runnable task, T result);
Runnable interfejs powinien być realizowany przez dowolną klasę, której instancje mają być realizowane przez Thread. Klasa musi zdefiniować metodę bez wywoływanych argumentów run.
Do wywołania : zadanie, które zwraca wynik i może zgłosić wyjątek. Implementatory definiują pojedynczą metodę bez argumentów nazywaną call. CallableInterfejs jest podobny do Runnable, ponieważ oba są przeznaczone dla klas, których przykłady są potencjalnie wykonywane przez inny gwint. A Runnablenie zwraca jednak wyniku i nie może zgłosić sprawdzonego wyjątku.
Inne różnice:
Możesz przejść, Runnableaby utworzyć wątek . Ale nie można utworzyć nowego wątku, przekazując go Callablejako parametr. Można przekazać funkcję wywoływania tylko do ExecutorServiceinstancji.
publicclassHelloRunnableimplementsRunnable{publicvoid run(){System.out.println("Hello from a thread!");}publicstaticvoid main(String args[]){(newThread(newHelloRunnable())).start();}}
Użyj Runnabledo ognia i zapominaj połączeń. Służy Callabledo weryfikacji wyniku.
Callablemożna przekazać do metody invokeAll w przeciwieństwie do metody Runnable. Metody invokeAnyi invokeAllwykonywanie najbardziej przydatnych form wykonywania zbiorczego, wykonywanie zbioru zadań, a następnie oczekiwanie na ukończenie co najmniej jednego lub wszystkich
Trywialna różnica: nazwa metody do zaimplementowania => run()for Runnablei call()for Callable.
Jak już wspomniano tutaj, Callable jest stosunkowo nowym interfejsem i został wprowadzony jako część pakietu współbieżności. Z programami wykonawczymi można używać zarówno wywoływalnych, jak i uruchamialnych. Wątek klasy (który implementuje sam Runnable) obsługuje tylko Runnable.
Nadal możesz używać Runnable z executorami. Zaletą Callable jest to, że możesz wysłać go do executora i natychmiast odzyskać przyszły wynik, który zostanie zaktualizowany po zakończeniu wykonywania. To samo można zaimplementować w Runnable, ale w takim przypadku musisz samodzielnie zarządzać wynikami. Na przykład możesz utworzyć kolejkę wyników, w której będą przechowywane wszystkie wyniki. Inny wątek może poczekać w tej kolejce i poradzić sobie z nadchodzącymi wynikami.
Zastanawiam się, jaki jest przykład wyjątku wyrzucającego wątek w Javie? czy główny wątek będzie w stanie wychwycić ten wyjątek? Jeśli nie, nie użyłbym Callable. Alex, masz na to jakiś wgląd? dzięki!
tryliony
1
Kod działający w niestandardowym wątku, jak każdy inny kod może zgłaszać wyjątek. Aby złapać go w innym wątku, musisz wykonać pewne wysiłki, używając niestandardowego mechanizmu powiadomień (np. FutureOpartego na słuchaczach) lub używając lub dodając hak, który przechwytuje wszystkie niewykrywane wyjątki: docs.oracle.com/javase/6/docs/api/ java / lang /…
AlexR
Świetna informacja! Dzięki, Alex! :)
tryliony
1
Poparłem tę odpowiedź, ponieważ zapewnia ona (poprawnie, jeśli jest pobierana według wartości nominalnej), należy użyć modelu puli wątków z obiektami, które można wywołać. Pozornie niefortunną rzeczą w tym jest to, że nie można rozszerzyć, Threadaby w znaczący sposób korzystać z Callableinterfejsu, tak aby można było dostosować pojedynczy wątek do robienia rzeczy na żądanie i innych rzeczy, których deweloper może chcieć. Jeśli ktoś, kto czyta ten komentarz, uważa, że się mylę, chciałbym wiedzieć lepiej ...
8
+-------------------------------------+--------------------------------------------------------------------------------------------------+|Runnable|Callable<T>|+-------------------------------------+--------------------------------------------------------------------------------------------------+|Introduced in Java1.0 of java.lang |Introduced in Java1.5 of java.util.concurrent library ||Runnable cannot be parametrized |Callable is a parametrized type whose type parameter indicates the return type of its run method ||Runnable has run() method |Callable has call() method ||Runnable.run() returns void|Callable.call() returns a value of Type T ||Can not throwCheckedExceptions|CanthrowCheckedExceptions|+-------------------------------------+--------------------------------------------------------------------------------------------------+
Projektanci Java odczuli potrzebę rozszerzenia możliwości Runnableinterfejsu, ale nie chcieli wpływać na wykorzystanie Runnableinterfejsu i prawdopodobnie dlatego zdecydowali się na osobny interfejs o nazwie CallableJava 1.5, niż zmieniający już istniejący Runnableinterfejs, który jest częścią Java od Java 1.0. źródło
Ważne jest, aby podkreślić, że zaznaczono wyjątek , a nie wyjątek RuntimeException
BertKing
5
Obie funkcje, które można wywoływać i wywoływać, są do siebie podobne i mogą być używane w implementacji wątku. W przypadku implementacji Runnable musisz zaimplementować metodę run () , ale w przypadku wywołania trzeba zaimplementować metodę call () , obie metody działają w podobny sposób, ale metoda call () ma większą elastyczność. Istnieją między nimi pewne różnice.
Różnica między Runnable i wymagalne jak below--
1) run () metoda przypisanymi zwrotu pustych , środków, jeśli chcesz coś powrotną wątek, który można wykorzystać dodatkowo wtedy masz żadnego wyboru z Runnable run () metody. Istnieje rozwiązanie „Callable”. Jeśli chcesz zwrócić dowolną rzecz w postaci obiektu , powinieneś użyć Callable zamiast Runnable . Interfejs na żądanie ma metodę „call ()”, która zwraca Object .
Podpis metody - Runnable->
publicvoid run(){}
Do wywołania->
publicObject call(){}
2) W przypadku Runnable run () metoda sprawdzona wyjątek jeśli powstaje wtedy trzeba trzeba obchodzić się z bloku try catch , ale w przypadku płatnych na żądanie call () metodę, która może rzucić wyjątek sprawdzenia jak poniżej
publicObject call()throwsException{}
3) Runnable pochodzi ze starszej wersji java 1.0 , ale można ją wywołać w wersji Java 1.5 ze środowiskiem Executer .
Jeśli znasz Executorów , powinieneś użyć Callable zamiast Runnable .
Runnable (vs) Callable zaczyna działać, gdy używamy frameworka Executer.
ExecutorService to podinterface Executor, który akceptuje zadania Runnable i Callable.
Wcześniej wiele wątków można osiągnąć za pomocą interfejsu od wersji 1.0 , ale tutaj problemem jest to, że po wykonaniu zadania wątku nie jesteśmy w stanie zebrać informacji o wątkach. W celu gromadzenia danych możemy użyć pól statycznych.Runnable
Przykład Oddzielne wątki, aby zebrać dane każdego ucznia.
staticHashMap<String,List> multiTasksData =newHashMap();publicstaticvoid main(String[] args){Thread t1 =newThread(newRunnableImpl(1),"T1");Thread t2 =newThread(newRunnableImpl(2),"T2");Thread t3 =newThread(newRunnableImpl(3),"T3");
multiTasksData.put("T1",newArrayList());// later get the value and update it.
multiTasksData.put("T2",newArrayList());
multiTasksData.put("T3",newArrayList());}
Aby rozwiązać ten problem, wprowadzili od wersji 1.5, która zwraca wynik i może zgłosić wyjątek.Callable<V>
Pojedyncza metoda abstrakcyjna : Zarówno interfejs wywoływalny, jak i uruchamialny mają jedną metodę abstrakcyjną, co oznacza, że można jej używać w wyrażeniach lambda w Javie 8.
Odpowiedzi:
Zobacz wyjaśnienie tutaj .
źródło
Zasadniczo tak. Zobacz odpowiedzi na to pytanie . I javadoc dla
Callable
.Ponieważ
Runnable
interfejs nie może zrobić wszystkiego, coCallable
robi!Runnable
istnieje już od wersji Java 1.0, aleCallable
został wprowadzony tylko w wersji Java 1.5 ... do obsługi przypadków użycia, któreRunnable
nie obsługują. Teoretycznie zespół Java mógł zmienić sygnaturęRunnable.run()
metody, ale złamałoby to binarną kompatybilność z kodem wcześniejszym niż 1.5, wymagając ponownego przekodowania podczas migracji starego kodu Java do nowszych JVM. To DUŻY NIE-NIE. Java stara się być kompatybilna wstecz ... i to był jeden z największych punktów sprzedaży Java dla komputerów biznesowych.Oczywiście są przypadki użycia, w których zadanie nie musi zwracać wyniku ani zgłaszać sprawdzonego wyjątku. W przypadku tych przypadków użycie
Runnable
jest bardziej zwięzłe niż użycieCallable<Void>
i zwrócenie wartości dummy (null
) zcall()
metody.źródło
Runnable
istnieje (w dużej mierze) ze względu na kompatybilność wsteczną. Ale czy nie są sytuacje, w których wdrożenie (lub wymaganie)Callable
interfejsu (np. WScheduledFuture<?> ScheduledExecutorService.schedule(Runnable command, long delay, TimeUnit unit)
) jest niepotrzebne lub zbyt drogie ? Czy zatem utrzymanie obu interfejsów w języku nie ma żadnej korzyści, nawet historia nie wymusiła obecnego wyniku?Runnable
zostałby zmodyfikowany, gdyby nie było konieczności zachowania zgodności. „Płyta kotła”return null;
jest słabym argumentem. (Przynajmniej taka byłaby moja decyzja ... w hipotetycznym kontekście, w którym można zignorować wsteczną kompatybilność.)Callable
Musi wdrożyćcall()
metody natomiastRunnable
musi wdrożyćrun()
metody.Callable
może zwrócić wartość, aleRunnable
nie może.Callable
Może rzucić wyjątek sprawdzone aleRunnable
nie mogę.Callable
Może być używany zExecutorService#invokeXXX(Collection<? extends Callable<T>> tasks)
metod, aleRunnable
nie może być.źródło
Znalazłem to na innym blogu, który może wyjaśnić nieco więcej tych różnic :
Chociaż oba interfejsy są implementowane przez klasy, które chcą wykonać w innym wątku wykonania, ale istnieje kilka różnic między tymi dwoma interfejsami, które są:
Callable<V>
Instancji zwraca wynik typuV
, podczas gdyRunnable
instancja nie.Callable<V>
Instancja może rzucać sprawdzonych wyjątków, natomiastRunnable
instancji nie możeProjektanci Java odczuli potrzebę rozszerzenia możliwości
Runnable
interfejsu, ale nie chcieli wpływać na wykorzystanieRunnable
interfejsu i prawdopodobnie dlatego zdecydowali się na osobny interfejs o nazwieCallable
Java 1.5, niż zmieniający już istniejącychRunnable
.źródło
Przyjrzyjmy się, gdzie można użyć Runnable i Callable.
Zarówno Runnable, jak i Callable działają na innym wątku niż wątek wywołujący. Ale Callable może zwrócić wartość, a Runnable nie. Gdzie to naprawdę ma zastosowanie.
Runnable : Jeśli masz zadanie pożaru i zapomnienia, użyj Runnable. Umieść swój kod w Runnable, a po wywołaniu metody run () możesz wykonać swoje zadanie. Wątek wywołujący naprawdę nie ma znaczenia podczas wykonywania zadania.
Callable : Jeśli próbujesz odzyskać wartość z zadania, użyj Callable. Teraz samodzielne wywołanie nie zadziała. Będziesz potrzebować Przyszłości, którą obejmiesz na żądanie i uzyskasz wartości na future.get (). Tutaj wątek wywołujący zostanie zablokowany, aż Przyszłość powróci z wynikami, które z kolei czekają na wykonanie metody call () Callable.
Pomyśl więc o interfejsie do klasy docelowej, w którym zdefiniowano zarówno metody zawijalne Runnable, jak i Callable. Klasa wywołująca losowo wywołuje metody interfejsu, nie wiedząc, która jest Runnable, a która Callable. Metody Runnable będą wykonywane asynchronicznie, dopóki nie zostanie wywołana metoda Callable. Tutaj wątek klasy wywołującej zostanie zablokowany, ponieważ pobierasz wartości z klasy docelowej.
UWAGA: W klasie docelowej można wykonywać wywołania do wywoływania i uruchamiania na jednym executorze wątków, co czyni ten mechanizm podobny do szeregowej kolejki wysyłania. Tak długo, jak wywołujący wywoła metody opakowane w Runnable, wątek wywołujący będzie działał naprawdę szybko bez blokowania. Gdy tylko wywoła metodę Callable zawiniętą w metodę Future, będzie musiała blokować do momentu wykonania wszystkich pozostałych pozycji w kolejce. Dopiero wtedy metoda zwróci wartości. To jest mechanizm synchronizacji.
źródło
Callable
interfejs deklarujecall()
metodę i należy podać ogólne, ponieważ typ wywołania obiektu () powinien zwrócić -Runnable
z drugiej strony jest interfejs, który deklarujerun()
metodę, która jest wywoływana podczas tworzenia wątku z runnable i wywołuje na nim start (). Możesz także bezpośrednio wywołać run (), ale to po prostu uruchamia metodę run () w tym samym wątku.Podsumowując kilka znaczących różnic
Runnable
Obiekt nie zwraca wynik podczas gdyCallable
obiekt zwraca wynik.Runnable
Obiekt nie może rzucać sprawdzonej wyjątek ubezpieczeniowyCallable
obiekt może rzucić wyjątek.Runnable
Interfejs istnieje od Java 1.0 natomiastCallable
został wprowadzony dopiero w Javie 1.5.Kilka podobieństw obejmuje
Metody w interfejsie ExecutorService są
źródło
Cel tych interfejsów z dokumentacji Oracle:
Runnable interfejs powinien być realizowany przez dowolną klasę, której instancje mają być realizowane przez
Thread
. Klasa musi zdefiniować metodę bez wywoływanych argumentówrun
.Do wywołania : zadanie, które zwraca wynik i może zgłosić wyjątek. Implementatory definiują pojedynczą metodę bez argumentów nazywaną call.
Callable
Interfejs jest podobny doRunnable
, ponieważ oba są przeznaczone dla klas, których przykłady są potencjalnie wykonywane przez inny gwint. ARunnable
nie zwraca jednak wyniku i nie może zgłosić sprawdzonego wyjątku.Inne różnice:
Możesz przejść,
Runnable
aby utworzyć wątek . Ale nie można utworzyć nowego wątku, przekazując goCallable
jako parametr. Można przekazać funkcję wywoływania tylko doExecutorService
instancji.Przykład:
Użyj
Runnable
do ognia i zapominaj połączeń. SłużyCallable
do weryfikacji wyniku.Callable
można przekazać do metody invokeAll w przeciwieństwie do metodyRunnable
. MetodyinvokeAny
iinvokeAll
wykonywanie najbardziej przydatnych form wykonywania zbiorczego, wykonywanie zbioru zadań, a następnie oczekiwanie na ukończenie co najmniej jednego lub wszystkichTrywialna różnica: nazwa metody do zaimplementowania =>
run()
forRunnable
icall()
forCallable
.źródło
Jak już wspomniano tutaj, Callable jest stosunkowo nowym interfejsem i został wprowadzony jako część pakietu współbieżności. Z programami wykonawczymi można używać zarówno wywoływalnych, jak i uruchamialnych. Wątek klasy (który implementuje sam Runnable) obsługuje tylko Runnable.
Nadal możesz używać Runnable z executorami. Zaletą Callable jest to, że możesz wysłać go do executora i natychmiast odzyskać przyszły wynik, który zostanie zaktualizowany po zakończeniu wykonywania. To samo można zaimplementować w Runnable, ale w takim przypadku musisz samodzielnie zarządzać wynikami. Na przykład możesz utworzyć kolejkę wyników, w której będą przechowywane wszystkie wyniki. Inny wątek może poczekać w tej kolejce i poradzić sobie z nadchodzącymi wynikami.
źródło
Future
Opartego na słuchaczach) lub używając lub dodając hak, który przechwytuje wszystkie niewykrywane wyjątki: docs.oracle.com/javase/6/docs/api/ java / lang /…Thread
aby w znaczący sposób korzystać zCallable
interfejsu, tak aby można było dostosować pojedynczy wątek do robienia rzeczy na żądanie i innych rzeczy, których deweloper może chcieć. Jeśli ktoś, kto czyta ten komentarz, uważa, że się mylę, chciałbym wiedzieć lepiej ...Projektanci Java odczuli potrzebę rozszerzenia możliwości
Runnable
interfejsu, ale nie chcieli wpływać na wykorzystanieRunnable
interfejsu i prawdopodobnie dlatego zdecydowali się na osobny interfejs o nazwieCallable
Java 1.5, niż zmieniający już istniejącyRunnable
interfejs, który jest częścią Java od Java 1.0. źródłoźródło
Różnice między wywoływalnymi i uruchamialnymi są następujące:
źródło
Obie funkcje, które można wywoływać i wywoływać, są do siebie podobne i mogą być używane w implementacji wątku. W przypadku implementacji Runnable musisz zaimplementować metodę run () , ale w przypadku wywołania trzeba zaimplementować metodę call () , obie metody działają w podobny sposób, ale metoda call () ma większą elastyczność. Istnieją między nimi pewne różnice.
Różnica między Runnable i wymagalne jak below--
1) run () metoda przypisanymi zwrotu pustych , środków, jeśli chcesz coś powrotną wątek, który można wykorzystać dodatkowo wtedy masz żadnego wyboru z Runnable run () metody. Istnieje rozwiązanie „Callable”. Jeśli chcesz zwrócić dowolną rzecz w postaci obiektu , powinieneś użyć Callable zamiast Runnable . Interfejs na żądanie ma metodę „call ()”, która zwraca Object .
Podpis metody - Runnable->
Do wywołania->
2) W przypadku Runnable run () metoda sprawdzona wyjątek jeśli powstaje wtedy trzeba trzeba obchodzić się z bloku try catch , ale w przypadku płatnych na żądanie call () metodę, która może rzucić wyjątek sprawdzenia jak poniżej
3) Runnable pochodzi ze starszej wersji java 1.0 , ale można ją wywołać w wersji Java 1.5 ze środowiskiem Executer .
Jeśli znasz Executorów , powinieneś użyć Callable zamiast Runnable .
Nadzieję, że rozumiesz.
źródło
Runnable (vs) Callable zaczyna działać, gdy używamy frameworka Executer.
ExecutorService to podinterface
Executor
, który akceptuje zadania Runnable i Callable.Wcześniej wiele wątków można osiągnąć za pomocą interfejsu od wersji 1.0 , ale tutaj problemem jest to, że po wykonaniu zadania wątku nie jesteśmy w stanie zebrać informacji o wątkach. W celu gromadzenia danych możemy użyć pól statycznych.
Runnable
Przykład Oddzielne wątki, aby zebrać dane każdego ucznia.
Aby rozwiązać ten problem, wprowadzili od wersji 1.5, która zwraca wynik i może zgłosić wyjątek.
Callable<V>
Pojedyncza metoda abstrakcyjna : Zarówno interfejs wywoływalny, jak i uruchamialny mają jedną metodę abstrakcyjną, co oznacza, że można jej używać w wyrażeniach lambda w Javie 8.
Istnieje kilka różnych sposobów delegowania zadań do wykonania w ExecutorService .
execute(Runnable task):void
tworzy nowy wątek, ale nie blokuje głównego wątku lub wątku wywołującego, ponieważ ta metoda zwraca wartość void.submit(Callable<?>):Future<?>
,submit(Runnable):Future<?>
tworzy nowy wątek i blokuje główny wątek, gdy używasz future.get () .Przykład użycia interfejsów Runnable, Callable with Executor Framework.
źródło
Jest to rodzaj konwencji nazewnictwa interfejsu, która pasuje do programowania funkcjonalnego
źródło