जवाबों:
स्पष्टीकरण यहाँ देखें ।
कॉल करने योग्य इंटरफ़ेस रननेबल के समान है, इसमें दोनों को उन वर्गों के लिए डिज़ाइन किया गया है जिनके उदाहरणों को संभावित रूप से किसी अन्य थ्रेड द्वारा निष्पादित किया जाता है। एक रननेबल, हालांकि, एक परिणाम नहीं लौटाता है और एक चेक अपवाद को फेंक नहीं सकता है।
Runnable
और के अनुप्रयोगों में क्या अंतर हैंCallable
। क्या अंतर केवल रिटर्न पैरामीटर में मौजूद हैCallable
?
असल में, हाँ। इस प्रश्न के उत्तर देखें । और के लिए javadocCallable
।
दोनों होने की क्या जरूरत है जो
Callable
सब कर सकताRunnable
है?
क्योंकि Runnable
इंटरफ़ेस सब कुछ नहीं करता है जो Callable
करता है!
Runnable
जावा 1.0 के बाद से आस-पास रहा है, लेकिन Callable
इसका उपयोग केवल जावा 1.5 में किया गया था ... उपयोग-मामलों को संभालने के लिए जो Runnable
समर्थन नहीं करता है। सिद्धांत रूप में, जावा टीम Runnable.run()
विधि के हस्ताक्षर को बदल सकती थी , लेकिन इससे प्री-1.5 कोड के साथ बाइनरी कॉम्पिटिबिलिटी टूट जाती, जब पुराने जावा कोड को नए जेवीएम में स्थानांतरित करने के लिए रीकोडिंग की आवश्यकता होती है। वह BIG NO-NO है। जावा पीछे की ओर संगत होने का प्रयास करता है ... और यह व्यवसाय कंप्यूटिंग के लिए जावा के सबसे बड़े विक्रय बिंदुओं में से एक है।
और, जाहिर है, ऐसे उपयोग-मामले हैं जहां किसी कार्य को परिणाम वापस करने या चेक किए गए अपवाद को फेंकने की आवश्यकता नहीं है। उन उपयोग-मामलों के लिए, विधि से डमी ( ) मान Runnable
का उपयोग करने Callable<Void>
और वापस करने की तुलना में उपयोग करना अधिक संक्षिप्त है ।null
call()
Runnable
पिछड़े संगतता कारणों के लिए (बड़े पैमाने पर) मौजूद है। लेकिन क्या ऐसी परिस्थितियाँ नहीं हैं जहाँ यह अनावश्यक या बहुत महंगा है (या आवश्यकता होती है) Callable
इंटरफ़ेस (जैसे, में ScheduledFuture<?> ScheduledExecutorService.schedule(Runnable command, long delay, TimeUnit unit)
) को लागू करने के लिए ? तो क्या भाषा में दोनों इंटरफेस बनाए रखने का कोई लाभ नहीं है, यहां तक कि इतिहास ने वर्तमान परिणाम को मजबूर नहीं किया है?
Runnable
तो इसे संशोधित किया जाएगा । का "बॉयलरप्लेट" return null;
एक कमजोर तर्क है। (कम से कम, यह मेरा फैसला होगा ... काल्पनिक संदर्भ में, जहां आप पीछे की संगतता को नजरअंदाज कर सकते हैं।)
Callable
को लागू करने की जरूरत है call()
विधि थोड़ी देर Runnable
जरूरतों को लागू करने की run()
विधि।Callable
मान वापस कर सकता है, लेकिन Runnable
नहीं कर सकता।Callable
चेक अपवाद को फेंक सकता है लेकिन ऐसा Runnable
नहीं कर सकता।A Callable
का उपयोग ExecutorService#invokeXXX(Collection<? extends Callable<T>> tasks)
विधियों के साथ किया जा सकता है लेकिन Runnable
नहीं हो सकता।
public interface Runnable {
void run();
}
public interface Callable<V> {
V call() throws Exception;
}
मैंने इसे एक अन्य ब्लॉग में पाया जो इन अंतरों को थोड़ा और समझा सकता है :
यद्यपि दोनों इंटरफेस उन वर्गों द्वारा कार्यान्वित किए जाते हैं जो निष्पादन के एक अलग धागे में निष्पादित करना चाहते हैं, लेकिन दो इंटरफ़ेस के बीच कुछ अंतर हैं:
Callable<V>
उदाहरण प्रकार का परिणाम देता है V
, जबकि एक Runnable
उदाहरण नहीं देता है।Callable<V>
उदाहरण जाँच अपवाद को फेंक सकता है, जबकि एक Runnable
उदाहरण नहीं हो सकताजावा के डिजाइनरों ने Runnable
इंटरफ़ेस की क्षमताओं को विस्तारित करने की आवश्यकता महसूस की , लेकिन वे इंटरफ़ेस के उपयोग को प्रभावित नहीं करना चाहते थे Runnable
और शायद यही कारण था कि वे Callable
पहले से ही बदलने की तुलना में जावा 1.5 में एक अलग इंटरफ़ेस रखने के लिए गए थे। मौजूदा Runnable
।
आइए हम देखें कि कोई व्यक्ति Runnable और Callable का उपयोग कहां करेगा।
रननेबल और कॉलेबल दोनों ही कॉलिंग थ्रेड से अलग थ्रेड पर चलते हैं। लेकिन Callable एक मान लौटा सकता है और Runnable नहीं कर सकता। तो यह वास्तव में कहां लागू होता है।
Runnable : यदि आपके पास आग है और कार्य भूल जाते हैं, तो Runnable का उपयोग करें। अपने कोड को रननेबल के अंदर रखें और जब रन () विधि कहा जाता है, तो आप अपना कार्य कर सकते हैं। कॉलिंग थ्रेड वास्तव में परवाह नहीं करता है जब आप अपना कार्य करते हैं।
कॉल करने योग्य : यदि आप किसी कार्य से मान प्राप्त करने का प्रयास कर रहे हैं, तो कॉल करने योग्य का उपयोग करें। अब कॉल करने योग्य अपने आप काम नहीं करेगा। आपको एक Future की आवश्यकता होगी जिसे आप अपने Callable के चारों ओर लपेटते हैं और Future.get () पर अपने मान प्राप्त करते हैं। यहां कॉलिंग थ्रेड को तब तक के लिए ब्लॉक कर दिया जाएगा जब तक कि फ्यूचर रिजल्ट के साथ वापस नहीं आ जाता है, जिसके परिणामस्वरूप कॉल करने योग्य कॉल () विधि को निष्पादित करने की प्रतीक्षा है।
तो एक लक्ष्य वर्ग के लिए एक इंटरफ़ेस के बारे में सोचें जहां आपके पास रननेबल और कॉल करने योग्य दोनों लिपटे हुए तरीके हैं। कॉलिंग क्लास आपके इंटरफ़ेस के तरीकों को बेतरतीब ढंग से कॉल करेगा जो यह नहीं जानता है कि कौन सा Runnable है और कौन से Callable है। जब तक किसी कॉल करने योग्य विधि को नहीं बुलाया जाता है, तब तक Runnable Methods एसिंक्रोनस रूप से निष्पादित होंगे। यहां कॉलिंग क्लास का थ्रेड ब्लॉक हो जाएगा क्योंकि आप अपने टारगेट क्लास से मान प्राप्त कर रहे हैं।
नोट: अपने लक्ष्य वर्ग के अंदर आप कॉल और रन करने योग्य को एक थ्रेड निष्पादक पर बना सकते हैं, जिससे यह तंत्र एक सीरियल प्रेषण कतार के समान हो जाता है। इसलिए जब तक कॉलर आपके रननेबल लिपटे हुए तरीकों को कॉल करता है तब तक कॉलिंग थ्रेड बिना ब्लॉक किए वास्तव में तेजी से निष्पादित होगा। जैसे ही यह भविष्य की विधि में लिपटे एक कॉल करने योग्य कॉल करता है, इसे तब तक ब्लॉक करना होगा जब तक कि अन्य सभी पंक्तिबद्ध वस्तुओं को निष्पादित नहीं किया जाता है। तभी विधि मूल्यों के साथ वापस आ जाएगी। यह एक सिंक्रनाइज़ेशन तंत्र है।
Callable
इंटरफ़ेस call()
विधि की घोषणा करता है और आपको ऑब्जेक्ट कॉल के प्रकार के रूप में जेनरिक प्रदान करना चाहिए () वापस आना चाहिए -
public interface Callable<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() throws Exception;
}
Runnable
दूसरी ओर वह इंटरफ़ेस है जो run()
विधि की घोषणा करता है जिसे कहा जाता है जब आप रन करने योग्य और कॉल प्रारंभ () के साथ एक थ्रेड बनाते हैं। आप सीधे रन रन () भी कह सकते हैं, लेकिन बस रन को निष्पादित करें () विधि समान थ्रेड है।
public interface Runnable {
/**
* 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()
*/
public abstract void run();
}
संक्षेप में कुछ उल्लेखनीय अंतर हैं
Runnable
, जबकि एक वस्तु एक परिणाम वापस नहीं करता Callable
वस्तु एक परिणाम देता है।Runnable
वस्तु एक अपवाद को नहीं छोड़ Callable
सकती है।Runnable
इंटरफ़ेस जावा 1.0 के बाद से आसपास किया गया है, जबकि Callable
केवल जावा 1.5 में पेश किया गया था।कुछ समानताओं में शामिल हैं
ExecutorService इंटरफ़ेस में विधियाँ हैं
<T> Future<T> submit(Callable<T> task);
Future<?> submit(Runnable task);
<T> Future<T> submit(Runnable task, T result);
ओरेकल प्रलेखन से इन इंटरफेस का उद्देश्य:
रनने योग्य इंटरफ़ेस को किसी भी वर्ग द्वारा लागू किया जाना चाहिए जिनके उदाहरणों को ए द्वारा निष्पादित किया जाना है Thread
। वर्ग को बिना किसी तर्क के एक विधि को परिभाषित करना चाहिए run
।
कॉल करने योग्य : एक कार्य जो एक परिणाम देता है और एक अपवाद फेंक सकता है। कार्यान्वयनकर्ता एकल पद्धति को परिभाषित करता है जिसका कोई तर्क नहीं है जिसे कॉल कहा जाता है। Callable
इंटरफ़ेस के समान है Runnable
में है कि दोनों वर्गों जिसका उदाहरणों संभवतः एक और धागा द्वारा क्रियान्वित कर रहे के लिए तैयार कर रहे हैं,। ए Runnable
, हालांकि, एक परिणाम नहीं लौटाता है और एक जाँच अपवाद को फेंक नहीं सकता है।
अन्य अंतर:
आप Runnable
एक थ्रेड बनाने के लिए पास कर सकते हैं । लेकिन आप Callable
पैरामीटर के रूप में पास करके नया थ्रेड नहीं बना सकते । आप केवल ExecutorService
उदाहरण के लिए Callable पास कर सकते हैं ।
public class HelloRunnable implements Runnable {
public void run() {
System.out.println("Hello from a thread!");
}
public static void main(String args[]) {
(new Thread(new HelloRunnable())).start();
}
}
Runnable
आग और भूल कॉल का उपयोग करें । Callable
परिणाम को सत्यापित करने के लिए उपयोग करें ।
Callable
विपरीत invokeAll विधि के लिए पारित किया जा सकता है Runnable
। तरीके invokeAny
और invokeAll
थोक निष्पादन के सबसे उपयोगी रूपों को निष्पादित करते हैं, कार्यों के संग्रह को निष्पादित करते हैं और फिर कम से कम एक, या सभी को पूरा करने की प्रतीक्षा करते हैं
तुच्छ अंतर: विधि का नाम लागू करने के लिए => के run()
लिए Runnable
और के call()
लिए Callable
।
जैसा कि यह पहले ही उल्लेख किया गया था कि कॉलेबल अपेक्षाकृत नया इंटरफ़ेस है और इसे कॉनक्योरिटी पैकेज के एक भाग के रूप में पेश किया गया था। निष्पादन योग्य के साथ Callable और Runnable दोनों का उपयोग किया जा सकता है। क्लास थ्रेड (जो कि रननेबल को लागू करता है) केवल रननेबल का समर्थन करता है।
आप अभी भी निष्पादन योग्य के साथ Runnable का उपयोग कर सकते हैं। Callable का लाभ जो आप इसे निष्पादक को भेज सकते हैं और तुरंत भविष्य का परिणाम प्राप्त कर सकते हैं जो निष्पादन समाप्त होने पर अपडेट किया जाएगा। वही रननेबल के साथ लागू किया जा सकता है, लेकिन इस मामले में आपको परिणामों का प्रबंधन स्वयं करना होगा। उदाहरण के लिए आप परिणाम कतार बना सकते हैं जो सभी परिणाम आयोजित करेगी। अन्य धागे इस कतार पर प्रतीक्षा कर सकते हैं और आने वाले परिणामों से निपट सकते हैं।
Future
या हुक लगाकर या बिना किसी अपवाद के सभी कैच को जोड़कर कुछ प्रयास करने होंगे: docs.oracle.com/javase/6/docs/apn/ java / lang /…
Thread
का सार्थक उपयोग करने के लिए विस्तार नहीं कर सकता Callable
है ताकि एक एकल थ्रेड को कॉल करने योग्य चीजों और अन्य चीजों को करने के लिए अनुकूलित किया जा सके जो डेवलपर को चाहिए। अगर कोई भी इस टिप्पणी को पढ़ता है, तो मुझे लगता है कि मैं गलत हूं, मैं बेहतर जानना चाहता हूं ...
+-------------------------------------+--------------------------------------------------------------------------------------------------+
| Runnable | Callable<T> |
+-------------------------------------+--------------------------------------------------------------------------------------------------+
| Introduced in Java 1.0 of java.lang | Introduced in Java 1.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 throw Checked Exceptions | Can throw Checked Exceptions |
+-------------------------------------+--------------------------------------------------------------------------------------------------+
जावा के डिजाइनरों ने Runnable
इंटरफ़ेस की क्षमताओं को विस्तारित करने की आवश्यकता महसूस की , लेकिन वे इंटरफ़ेस के उपयोग को प्रभावित नहीं करना चाहते थे Runnable
और शायद यही कारण था कि वे Callable
पहले से ही बदलने की तुलना में जावा 1.5 में एक अलग इंटरफ़ेस रखने के लिए गए थे। मौजूदा Runnable
इंटरफ़ेस जो जावा 1.0 के बाद से जावा का एक हिस्सा रहा है। स्रोत
Callable और Runnable के बीच अंतर निम्नलिखित हैं:
कॉल करने योग्य और रन करने योग्य दोनों एक दूसरे के समान हैं और धागे को लागू करने में उपयोग कर सकते हैं। रननेबल को लागू करने के मामले में आपको रन () विधि को लागू करना होगा लेकिन कॉल करने योग्य के मामले में आपको कॉल () विधि को लागू करने की आवश्यकता होगी , दोनों विधि समान तरीके से काम करती हैं लेकिन कॉल करने योग्य कॉल () विधि में अधिक लचीलापन होता है। उनके बीच कुछ अंतर है।
के बीच अंतर Runnable और प्रतिदेय below-- के रूप में
1) रन () की विधि runnable रिटर्न शून्य , साधन आप अपने धागा वापसी कुछ जो आप आगे तो आप उपयोग कर सकते हैं चाहते हैं, तो Runnable रन () के साथ और कोई चारा नहीं विधि। एक समाधान है 'कॉल करने योग्य' , यदि आप वस्तु के रूप में किसी भी चीज को वापस करना चाहते हैं तो आपको रननेबल के बजाय कॉल करने योग्य का उपयोग करना चाहिए । कॉल करने योग्य इंटरफ़ेस में विधि 'कॉल ()' है जो ऑब्जेक्ट लौटाता है ।
विधि हस्ताक्षर - Runnable->
public void run(){}
Callable->
public Object call(){}
2) रन करने योग्य रन () विधि के मामले में यदि कोई भी चेक किया गया अपवाद उत्पन्न होता है, तो आपको कोशिश पकड़ने वाले ब्लॉक से निपटने की आवश्यकता होगी , लेकिन कॉल करने योग्य कॉल () विधि के मामले में आप नीचे दिए गए अपवाद को फेंक सकते हैं।
public Object call() throws Exception {}
3) Runnable विरासत से आता है जावा 1.0 संस्करण है, लेकिन प्रतिदेय में आया था जावा 1.5 के साथ संस्करण निष्पादनकर्ता ढांचा।
यदि आप Executers से परिचित हैं तो आपको Runnable के बजाय Callable का उपयोग करना चाहिए ।
उम्मीद है आप समझ गए होंगे।
Runnable (बनाम) Callable तब आता है जब हम Executer ढांचे का उपयोग कर रहे हैं।
ExecutorService एक उपप्रकार है Executor
, जो दोनों Runnable और Callable कार्यों को स्वीकार करता है।
पहले मल्टी-थ्रेडिंग को 1.0 के बाद से इंटरफ़ेस का उपयोग करके प्राप्त किया जा सकता है , लेकिन यहां समस्या यह है कि थ्रेड कार्य को पूरा करने के बाद हम थ्रेड्स जानकारी एकत्र करने में असमर्थ हैं। डेटा एकत्र करने के लिए हम स्थैतिक क्षेत्रों का उपयोग कर सकते हैं।Runnable
उदाहरण प्रत्येक छात्र डेटा एकत्र करने के लिए थ्रेड्स अलग करें।
static HashMap<String, List> multiTasksData = new HashMap();
public static void main(String[] args) {
Thread t1 = new Thread( new RunnableImpl(1), "T1" );
Thread t2 = new Thread( new RunnableImpl(2), "T2" );
Thread t3 = new Thread( new RunnableImpl(3), "T3" );
multiTasksData.put("T1", new ArrayList() ); // later get the value and update it.
multiTasksData.put("T2", new ArrayList() );
multiTasksData.put("T3", new ArrayList() );
}
इस समस्या को हल करने के लिए उन्होंने 1.5 से पेश किया है जो एक परिणाम देता है और एक अपवाद फेंक सकता है।Callable<V>
सिंगल एब्सट्रैक्ट मेथड : कॉल करने योग्य और रन करने योग्य इंटरफ़ेस दोनों में एक ही अमूर्त विधि है, जिसका अर्थ है कि उनका उपयोग जावा 8 में लैम्ब्डा एक्सप्रेशन में किया जा सकता है।
public interface Runnable {
public void run();
}
public interface Callable<Object> {
public Object call() throws Exception;
}
ExecutorService को निष्पादित करने के लिए कार्यों को सौंपने के लिए कुछ अलग तरीके हैं ।
execute(Runnable task):void
नए धागे को क्रेट करता है लेकिन मुख्य थ्रेड या कॉलर थ्रेड को ब्लॉक नहीं करता है क्योंकि यह विधि वापस आती है।submit(Callable<?>):Future<?>
submit(Runnable):Future<?>
जब आप भविष्य का उपयोग कर रहे हों , तो नए धागे को काटता है और मुख्य धागे को ब्लॉक करता है । ()Interfaces Runnable, Callable with Executor फ्रेमवर्क का उपयोग करने का उदाहरण।
class CallableTask implements Callable<Integer> {
private int num = 0;
public CallableTask(int num) {
this.num = num;
}
@Override
public Integer call() throws Exception {
String threadName = Thread.currentThread().getName();
System.out.println(threadName + " : Started Task...");
for (int i = 0; i < 5; i++) {
System.out.println(i + " : " + threadName + " : " + num);
num = num + i;
MainThread_Wait_TillWorkerThreadsComplete.sleep(1);
}
System.out.println(threadName + " : Completed Task. Final Value : "+ num);
return num;
}
}
class RunnableTask implements Runnable {
private int num = 0;
public RunnableTask(int num) {
this.num = num;
}
@Override
public void run() {
String threadName = Thread.currentThread().getName();
System.out.println(threadName + " : Started Task...");
for (int i = 0; i < 5; i++) {
System.out.println(i + " : " + threadName + " : " + num);
num = num + i;
MainThread_Wait_TillWorkerThreadsComplete.sleep(1);
}
System.out.println(threadName + " : Completed Task. Final Value : "+ num);
}
}
public class MainThread_Wait_TillWorkerThreadsComplete {
public static void main(String[] args) throws InterruptedException, ExecutionException {
System.out.println("Main Thread start...");
Instant start = java.time.Instant.now();
runnableThreads();
callableThreads();
Instant end = java.time.Instant.now();
Duration between = java.time.Duration.between(start, end);
System.out.format("Time taken : %02d:%02d.%04d \n", between.toMinutes(), between.getSeconds(), between.toMillis());
System.out.println("Main Thread completed...");
}
public static void runnableThreads() throws InterruptedException, ExecutionException {
ExecutorService executor = Executors.newFixedThreadPool(4);
Future<?> f1 = executor.submit( new RunnableTask(5) );
Future<?> f2 = executor.submit( new RunnableTask(2) );
Future<?> f3 = executor.submit( new RunnableTask(1) );
// Waits until pool-thread complete, return null upon successful completion.
System.out.println("F1 : "+ f1.get());
System.out.println("F2 : "+ f2.get());
System.out.println("F3 : "+ f3.get());
executor.shutdown();
}
public static void callableThreads() throws InterruptedException, ExecutionException {
ExecutorService executor = Executors.newFixedThreadPool(4);
Future<Integer> f1 = executor.submit( new CallableTask(5) );
Future<Integer> f2 = executor.submit( new CallableTask(2) );
Future<Integer> f3 = executor.submit( new CallableTask(1) );
// Waits until pool-thread complete, returns the result.
System.out.println("F1 : "+ f1.get());
System.out.println("F2 : "+ f2.get());
System.out.println("F3 : "+ f3.get());
executor.shutdown();
}
}
यह एक प्रकार का इंटरफ़ेस नामकरण सम्मेलन है जो कार्यात्मक प्रोग्रामिंग के साथ मेल खाता है
//Runnable
interface Runnable {
void run();
}
//Action - throws exception
interface Action {
void run() throws Exception;
}
//Consumer - consumes a value/values, throws exception
interface Consumer1<T> {
void accept(T t) throws Exception;
}
//Callable - return result, throws exception
interface Callable<R> {
R call() throws Exception;
}
//Supplier - returns result, throws exception
interface Supplier<R> {
R get() throws Exception;
}
//Predicate - consumes a value/values, returns true or false, throws exception
interface Predicate1<T> {
boolean test(T t) throws Exception;
}
//Function - consumes a value/values, returns result, throws exception
public interface Function1<T, R> {
R apply(T t) throws Throwable;
}
...