2010-07-07 10 views
6

जावा का शेड्यूल WithFixedDelay एक रननेबल के साथ क्यों काम करता है लेकिन फ्यूचरटास्क एक रननेबल नहीं है?जावा का शेड्यूल WithFixedDelay एक रननेबल के साथ क्यों काम करता है लेकिन फ्यूचरटास्क <?> एक रननेबल को लपेटता नहीं है?

ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor(); 
     executorService.scheduleWithFixedDelay(new FutureTask<Integer>(new Callable<Integer>() { 

      @Override 
      public Integer call() throws Exception { 
       System.out.println("beep"); 
       return 1; 
      } 
     }), 1, 5, TimeUnit.SECONDS); 

पैदा करता है:

यह दो अलग-अलग कोड नमूने के साथ बहुत आसानी से दिखाया जा सकता है

बीप

लेकिन अनुप्रयोग से बाहर नहीं है, यह बस प्रतीक्षा करने के लिए प्रकट होता है ।

लेकिन:

ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor(); 
    executorService.scheduleWithFixedDelay(new Runnable() { 

     @Override 
     public void run() { 
      System.out.println("beep "); 
     } 
    }, 1, 5, TimeUnit.SECONDS); 

पैदा करता है:

बीप बीप बीप बीप

बीप 5 सेकंड के अंतराल पर।

ऐसा लगता है कि यहां कुछ प्रकार का लॉक हो रहा है जिसे मैं निर्धारित नहीं कर सकता।

+0

जब भी मैं अपना कोड चलाता हूं जो बीप बीप बीप बीप बीप का उत्पादन करता है, मुझे एक बीप भी नहीं मिलती है, और प्रक्रिया को निष्पादित करने से पहले खत्म हो जाती है। अगर मैं शुरुआती देरी को 1 से 0 में बदलता हूं, तो मुझे एक बीप मिलती है। – Marcus

+0

कभी नहीं, ऐसा इसलिए था क्योंकि इसे निष्पादित करने के लिए निष्पादक सेवा.वाइट टर्मिनेशन() को अवरुद्ध करने की आवश्यकता थी। – Marcus

उत्तर

13

क्योंकि आप FutureTask का दुरुपयोग कर रहे हैं।

जवाडॉक्स के अनुसार एक फ्यूचरटास्क "एक रद्द करने योग्य असीमित गणना" है, लेकिन अधिक बोलने वाला यह एसिंक्रोनिटी प्रदान करने के लिए रननेबल/कॉलबल के एक विशेष निष्पादन को लपेटता है। मुझे वास्तव में एहसास नहीं हुआ कि यह Runnable लागू किया गया है जब तक कि मैंने अभी चेक नहीं किया - run() का कार्यान्वयन "इस गणना को इसके गणना के परिणामस्वरूप सेट करता है"।

तो आपके पहले उदाहरण में क्या हो रहा है यह है कि आप भविष्य के कार्य को शेड्यूल कर रहे हैं, इसकी रन विधि 1 सेकंड के बाद कॉल की जाती है और इसलिए यह गणना के परिणाम की गणना करता है (यानी एम्बेडेड Runnable चलाता है)। जब यह विधि निकलती है, तो फ़्यूचरटास्क अब चला गया है और इसका ठोस परिणाम है - इसलिए रन() के भविष्य के आमंत्रण नो-ऑप्स हैं।

मुझे लगता है कि यहां मूल समस्या यह है कि कम से कम एक फ्यूचरटास्क शेड्यूल करने के लिए यह समझ में नहीं आता है, कम से कम इस तरह से नहीं कि आप यहां क्या कर रहे हैं। यदि आप प्रत्येक पांच सेकंड चलाने के लिए थोड़ा कोड चाहते हैं, तो आपको निश्चित रूप से दूसरा दृष्टिकोण लेना चाहिए। फ्यूचरटास्क एक (एकल!) गणना का प्रतीक है; ऐसा कोई कारण नहीं है कि आप इसे कई बार क्यों बुलाया जाए और वास्तव में यह इसे रोकने के लिए परिणाम को कैशिंग कर रहा है।

+1

यह एक अच्छा जवाब है धन्यवाद, मैं इस उदाहरण में एक रननेबल के साथ एक फ्यूचरटास्क का उपयोग कर रहा था, लेकिन बिजनेस केस, क्या मैं शेड्यूलर में एक कॉल करने योग्य जाम करने की कोशिश कर रहा था, और फ्यूचरटास्क एक तर्क के रूप में कॉल करने योग्य हो सकता था, और रननेबल इंटरफ़ेस को संतुष्ट करें। –

3

आप एक ScheduledExecutorService में FutureTask वस्तुओं पारित करने के लिए नहीं करना पड़ेगा, आप Runnable या Callable में पारित करने के लिए है, जो तब रिटर्न आप एक FutureTask चाहिए रहे हैं। तथ्य यह है कि FutureTask लागू करता है Runnable इंटरफ़ेस एक दुर्भाग्यपूर्ण डिज़ाइन दोष लगता है, जिससे आप आउटपुट को इनपुट के रूप में वापस ले सकते हैं।

आपको यह व्यवहार क्यों मिलता है, यह संभवतः घटकों के बीच कुछ अजीब बातचीत है, और शायद अपरिभाषित है।

संबंधित मुद्दे