ScheduledExecutorService scheduleWithFixedDelay या scheduleAtFixedRate का उपयोग करते समय 0 समय इकाइयों के initialDelay के साथ सबमिट किए गए कार्य को निष्पादित नहीं करना। लेकिन जब मैं schedule उस पर

ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
Runnable runnable = () -> System.out.println("I am a runnable");
scheduledExecutorService.schedule(runnable, 0, TimeUnit.SECONDS);
scheduledExecutorService.shutdown();

उत्पादन

I am a runnable

लेकिन जब मैं schedule के बजाय scheduleWithFixedDelay या scheduleAtFixedRate का उपयोग करता हूं तो कार्य निष्पादित नहीं हो रहा है।

ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
Runnable runnable = () -> System.out.println("I am a runnable");
scheduledExecutorService.scheduleWithFixedDelay(runnable, 0, 1, TimeUnit.SECONDS);
// or  scheduledExecutorService.scheduleAtFixedRate(runnable, 0, 1, TimeUnit.SECONDS);
scheduledExecutorService.shutdown();

इस परिदृश्य में कार्य निष्पादित क्यों नहीं हो रहा है? मुझे उम्मीद थी कि यह कार्य निष्पादित हो जाएगा क्योंकि initialDelay 0 पर सेट है

3
Turtle 24 पद 2021, 10:08
फिर भी, जो अजीब बात है वह यह है कि मुझे scheduleWithFixedDelay या scheduleAtFixedRate के अंदर ScheduledThreadPoolExecutor में कोई async कॉल नहीं मिली, जिसके कारण ऐसा हो सकता है। यदि ऐसा नहीं है तो एपीआई कॉल को वापस करने से पहले कार्य को निष्पादित करने में कुछ ओवरहेड होना चाहिए।
 – 
Turtle
24 पद 2021, 11:52

4 जवाब

सबसे बढ़िया उत्तर

ExecutorService#shutdown आगे के टास्क शेड्यूल करना बंद कर देता है। जाहिरा तौर पर आपकी कॉल इतनी जल्दी होती है कि शेड्यूलर को निर्धारित कार्य के पहले भाग को निष्पादित करने के लिए कभी नहीं मिला। यह समझ में आता है।

इसका कोई मतलब नहीं है कि schedule को कॉल इतनी तेजी से क्यों शेड्यूल की जाती है कि शटडाउन से पहले अपने कार्य को समय पर पूरा किया जा सके, लेकिन scheduleWithFixedDelay या scheduleAtFixedRate को देरी से कॉल किया जाता है। शून्य के रूप में जल्दी से निर्धारित नहीं है। स्पष्ट रूप से scheduleWithFixedDelay और scheduleAtFixedRate कॉल में कुछ ओवरहेड है, पर्याप्त ओवरहेड है कि प्रोग्राम को अपना पहला निष्पादन करने का मौका मिलने से पहले बाहर निकलता है।

वैसे भी, आप अपने कोड के मेरे संस्करण में व्यवहार देख सकते हैं IdeOne.com पर लाइव चल रहा है। इस लाइन को जोड़ना:

Thread.sleep( 1_000 * 5 ) ;

... इससे पहले कि आपका शटडाउन कुछ scheduleWithFixedDelay और scheduleAtFixedRate कार्यों को निष्पादित करने के लिए पर्याप्त समय देता है।

या awaitTermination में कॉल जोड़कर वैसा ही प्रभाव देखें जैसा कि गुयेन द्वारा सही उत्तर में दिखाया गया है।

1
Basil Bourque 24 पद 2021, 10:59
अनुसूचित दोहराने कार्यों के लिए, इसका अर्थ है कि वर्तमान में चल रहे कार्य का निष्पादन समाप्त हो जाएगा, लेकिन उसके बाद उस कार्य की कोई और पुनरावृत्ति शेड्यूल नहीं की जाएगी। अन्यथा, हमारे पास दोहराए जाने वाले कार्यों को रोकने का कोई तरीका नहीं होगा।
 – 
Basil Bourque
24 पद 2021, 10:49
तुम्हें पता है क्या...मैं इस पर फ़्लॉप कर रहा हूँ। मुझे लगा कि प्रस्तुत भाषा ने इसे स्पष्ट कर दिया है, लेकिन मुझे लगता है कि आप सही हैं, यह किसी भी तरह से एक दौड़ की स्थिति है और 'अनुसूची; बस थोड़ा तेज हो सकता है। हो सकता है कि पर्याप्त रन देखने से वह चूक भी जाए।
 – 
matt
24 पद 2021, 10:51
2
सिद्धांत रूप में मुझे लगता है कि शून्य की देरी के साथ दोहराए जाने वाले कार्य को schedule कॉल के रूप में जल्दी से निष्पादित किया जाएगा। लेकिन जाहिरा तौर पर नहीं। जाहिरा तौर पर शेड्यूल में वास्तव में कुछ ओवरहेड है विथफिक्स्डडेल और शेड्यूलएटफिक्स्डरेट कॉल, पर्याप्त ओवरहेड है कि प्रोग्राम को अपना पहला निष्पादन करने का मौका मिलने से पहले बाहर निकलता है।
 – 
Basil Bourque
24 पद 2021, 10:54
मुझे लगता है कि @matt भी सही है, आम शब्दों में scheduleWithFixedDelay या scheduleAtFixedRate 0 की प्रारंभिक देरी के साथ शब्दार्थ को बनाए रखने के लिए निष्पादित किया जाना चाहिए
 – 
Turtle
24 पद 2021, 10:54
Apparently there is some overhead in the scheduleWithFixedDelay and scheduleAtFixedRate calls, enough overhead that the program exits before they get a chance to make their first executions. नमस्ते, तुलसी, इस मार्ग से मेरी कुछ असहमति है, मैंने एक उत्तर लिखा है, क्या आप देख सकते हैं
 – 
zysaaa
24 पद 2021, 11:57

आपने निष्पादक को बहुत जल्दी बंद कर दिया। इसलिए अन्य सूत्र अभी तक प्रारंभ नहीं हुआ है। इस बात की कोई गारंटी नहीं है कि थ्रेड पहले शटडाउन विधि से शुरू होगा।

यदि आप प्रतीक्षा टर्मिनेशन का उपयोग करते हैं तो आप आउटपुट देखेंगे।

scheduledExecutorService.awaitTermination(1, TimeUnit.MILLISECONDS);

// आउटपुट: मैं एक रननेबल हूं

1
Huy Nguyen 24 पद 2021, 10:41

इसके पीछे का कारण ScheduledThreadPoolExecutor में पाया जा सकता है, जो Executors.newSingleThreadScheduledExecutor() का कार्यान्वयन वर्ग है।

1. schedule को कॉल करते समय कार्य निष्पादित किया जाता है,

यह executingExistingDelayedTasksAfterShutdown डिफ़ॉल्ट रूप से सत्य है

    /**
     * False if should cancel non-periodic not-yet-expired tasks on shutdown.
     */
    private volatile boolean executeExistingDelayedTasksAfterShutdown = true;

2. scheduleWithFixedDelay या scheduleAtFixedRate के लिए कार्य निष्पादित नहीं किया गया है

यह continueExistingPeriodicTasksAfterShutdown डिफ़ॉल्ट रूप से गलत है

    /**
     * False if should cancel/suppress periodic tasks on shutdown.
     */
    private volatile boolean continueExistingPeriodicTasksAfterShutdown;

हम इन मापदंडों को ScheduledThreadPoolExecutor#setExecuteExistingDelayedTasksAfterShutdownPolicy और ScheduledThreadPoolExecutor#setContinueExistingPeriodicTasksAfterShutdownPolicy

1
samabcde 24 पद 2021, 11:09

shutdown को तुरंत क्यों बुलाया जाता है, schedule इस कार्य को कर सकता है, लेकिन scheduleAtFixedRate इस कार्य को नहीं करता है?

यदि scheduleAtFixedRate का उपयोग किया जाता है, तो यह कार्य Periodic है, और डिफ़ॉल्ट keepPeriodic नीति false है, इसलिए shutdown होने पर यह कार्य कार्य कतार से हटा दिया जाएगा बुलाया।

लेकिन schedule का उपयोग करने से कार्य को हटाने का तर्क नहीं होता है।(isPeriodic गलत है।)

देखें ScheduledThreadPoolExecutor#onShutdown:

        @Override void onShutdown() {
        BlockingQueue<Runnable> q = super.getQueue();
        boolean keepDelayed =
            getExecuteExistingDelayedTasksAfterShutdownPolicy();
        boolean keepPeriodic =
            getContinueExistingPeriodicTasksAfterShutdownPolicy();
        // Traverse snapshot to avoid iterator exceptions
        // TODO: implement and use efficient removeIf
        // super.getQueue().removeIf(...);
        for (Object e : q.toArray()) {
            if (e instanceof RunnableScheduledFuture) {
                RunnableScheduledFuture<?> t = (RunnableScheduledFuture<?>)e;
                if ((t.isPeriodic()
                     ? !keepPeriodic
                     : (!keepDelayed && t.getDelay(NANOSECONDS) > 0))
                    || t.isCancelled()) { // also remove if already cancelled
                    if (q.remove(t))
                        t.cancel(false);
                }
            }
        }
        tryTerminate();
    }

तो मुझे लगता है कि तुलसी बोर्के के जवाब से स्पष्टीकरण गलत है:

जाहिरा तौर पर शेड्यूल में कुछ ओवरहेड है विथफिक्स्डडेल और शेड्यूलएटफिक्स्डरेट कॉल, पर्याप्त ओवरहेड है कि प्रोग्राम को अपना पहला निष्पादन करने का मौका मिलने से पहले बाहर निकलता है।

ऐसा इसलिए नहीं है क्योंकि प्रोग्राम अपना पहला निष्पादन करने का मौका मिलने से पहले बाहर निकलता है, बल्कि इसलिए कि थ्रेड पूल में वर्कर थ्रेड्स को कार्य नहीं मिला (इसे हटा दिया गया था), और फिर थ्रेड पूल बंद हो गया। इस समय, प्रोग्राम बाहर निकलता है। यदि कार्य को नहीं हटाया जाता है, तो प्रोग्राम तुरंत बाहर नहीं निकलेगा। केवल जब थ्रेड पूल में वर्कर थ्रेड ने कार्य कतार में कार्य पूरा कर लिया है, तो प्रोग्राम बाहर निकल जाएगा। (क्योंकि थ्रेड पूल में वर्कर थ्रेड डेमन थ्रेड नहीं हैं)।

1
zysaaa 24 पद 2021, 11:53