2010-05-25 10 views
11

जब मैं ScheduledExecutorService.schedule() को कॉल करके थ्रेड बनाता हूं, तो यह निर्धारित कार्य निष्पादित करने के बाद कभी समाप्त नहीं होता है।शेड्यूलExecutorService.schedule() द्वारा शुरू किया गया थ्रेड कभी समाप्त नहीं होता है?

उदाहरण के लिए निम्नलिखित कार्यक्रम इस्तीफा कभी नहीं:

public static void main(String[] args) { 
    ScheduledFuture scheduledFuture = 
     Executors.newSingleThreadScheduledExecutor().schedule(new Callable() { 

    public Void call() { 
     doSomething(); 
     return null; 
    } 

    }, 1, TimeUnit.SECONDS); 
} 

public static void doSomething() { 
} 

यह एक JDK बग है, या मैं बस कुछ याद आया?

+0

क्या कुछ चल रहा है कुछ()? –

उत्तर

2

निष्पादन को रोकने के लिए आपको scheduledExecutorService.shutdown() पर कॉल करने की आवश्यकता है। अन्यथा यह हर सेकेंड को पुनरारंभ किया जाता है।

(संपादित: टिप्पणियाँ देखें)

+2

निर्धारितExecutorService को कॉल करना चाहिए।शेडडाउन() शेड्यूल के बजायFuture.shutdown(), और ScheduledExecutorService.schedule() कॉल एक-शॉट एक्शन है, जिसे दोबारा पुन: प्रारंभ नहीं किया जाएगा। – moonese

7

एक निर्धारित कार्य निष्पादित किया जा रहा है या तो है या का इन्तजार कर रहे है।

यदि कार्य निष्पादित होने का इंतजार कर रहा है, तो future.cancel() इसे निष्पादित होने से रोक देगा (दोनों रद्द (सत्य)/रद्द (झूठा))।

यदि कार्य पहले ही निष्पादित किया जा रहा है, future.cancel(false) का कोई प्रभाव नहीं पड़ेगा। future.cancel(true) उस कार्य को निष्पादित करने वाले थ्रेड को बाधित करेगा। क्या इसका कोई प्रभाव आपके लिए पर होगा, जो उस कार्य को लागू करेगा। एक कार्य कार्यान्वयन के आधार पर बाधा का जवाब दे सकता है या नहीं।

अपना कार्य रद्दीकरण के लिए उत्तरदायी बनाने के लिए, आपको doSomething() लागू करना होगा ताकि यह बाधा का जवाब दे सके।

यह करने के लिए मूल रूप से दो तरह से कर रहे हैं: अपने तर्क में

1.Check रुकावट झंडा

public void doSomething(){ 
    stuff(); 
    //Don't use Thread.interrupt() 
    if(Thread.currentThread().isInterrupted()){ 
     // We have an interruption request, possibly a cancel request 
     //Stop doing what you are doing and terminate. 
     return; 
    } 
    doLongRunningStuff(); 
} 

आप कभी-कभी रुकावट ध्वज के लिए जांच करना चाहिए, और अगर बाधित, बंद करो तुम क्या कर रहे और वापस। चेक के लिए Thread.isInterrupted() और Thread.interrupt() का उपयोग करना सुनिश्चित करें। बाधित अपवाद पर

2.Act

public void doSomething(){ 
    try{ 
     stuff(); 
    }catch(InterruptedException e){ 
     // We have an interruption request, possibly a cancel request 

     // First, preserve Interrupted Status because InterruptedException clears the 
     // interrupted flag 
     Thread.currentThread.interrupt(); 

     // Now stop doing your task and terminate 
     return; 
    } 

    doLongRunningStuff(); 
} 

आप किसी भी विधि का InterruptedException फेंकता है, तो रोक तुम क्या कर और उसे समाप्त कर जब एक फेंक दिया जाता है सुनिश्चित करें।

एक बार जब आप इस तरीके से अपनी विधियों को लागू कर लेते हैं, तो आप किसी चल रहे कार्य को निष्पादित करने के लिए future.cancel (true) को कॉल कर सकते हैं।

+0

कमांड को कॉल करने के बाद शेड्यूल को कैसे बंद करें? तो धागा संसाधन जारी करने के लिए। आखिरकार, शेड्यूल द्वारा बनाए गए कार्य को एक बार निष्पादित किया जाता है। – Nickolas

+0

@ निकोलस: सुनिश्चित नहीं है कि आपका क्या मतलब है, लेकिन यदि आपका मतलब एक ऐसा कार्य है जो एक बार चलाने के लिए निर्धारित किया गया था (देरी के बाद आदि) और यह पहले से ही पूरा हो चुका है, तो कार्य पहले से ही बंद हो गया होगा (और थ्रेड जारी किया जाएगा)। अन्यथा मेरा जवाब अभी भी लागू होता है। –

+1

यह एक अच्छा जवाब है लेकिन एक अलग सवाल के लिए। समस्या यह नहीं है कि कार्य को कैसे समाप्त किया जाए - ओपी स्पष्ट रूप से बताता है कि कार्य एक एनओपी है - लेकिन कार्य को चलाने के लिए प्रयुक्त थ्रेड को कैसे समाप्त किया जाए। – oberlies

5

आपका प्रोग्राम कभी समाप्त नहीं होता है क्योंकि आप ScheduledExecutorService बनाते हैं, जिसमें थ्रेड पूल होता है, लेकिन आपने कभी सेवा बंद नहीं की है। इसलिए, थ्रेड पूल में उपयोगकर्ता थ्रेड कभी समाप्त नहीं होते हैं, और इसलिए वीएम हमेशा के लिए चल रहा है।

इस समस्या को हल करने के लिए, आपको निष्पादक सेवा पर shutdown() पर कॉल करने की आवश्यकता है। यह भी काम आप पर अमल करना चाहते हैं का समय निर्धारण के बाद सीधे किया जा सकता है:

public static void main(String[] args) { 
    ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor(); 
    ScheduledFuture scheduledFuture = executorService.schedule(new Callable() { 

    public Void call() { 
     doSomething(); 
     return null; 
    } 

    }, 1, TimeUnit.SECONDS); 
    executorService.shutdown(); 
} 

यह निर्धारित कार्य सामान्य रूप से निष्पादित और फिर पूल में धागा समाप्त कर देगा।

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

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