2016-08-30 6 views
9

मेरे पास एक ऐसा एप्लिकेशन है जो उपयोगकर्ता क्रियाओं पर एक संदेश को छपने के लिए टाइमर शुरू करता है। जेडीके प्रोफाइलर में ऐसा लगता है कि जीसी (मुझे लगता है) द्वारा निष्पादन के बाद अन्य सभी धागे हटा दिए जा रहे हैं लेकिन बनाए गए टाइमर को हटाया नहीं जा रहा है। वहां क्या हो रहा है?जावा - निष्पादन के बाद टाइमर को हटाया नहीं जा रहा है

मेरी टाइमर:

/** 
* @param owner 
* @param added 
*/ 
public static void splashParentWithAnimation(AnchorPane owner, Parent added,double posX,double posY) { 
    // addParentWithAnimation(owner, added); 
    owner.getChildren().add(added); 

    AnchorPane.setLeftAnchor(added, posX); 

    AnchorPane.setTopAnchor(added, posY); 

    FadeTransition ft1 = new FadeTransition(Duration.millis(300), added); 
    ft1.setFromValue(0.0); 
    ft1.setToValue(1.0); 
    ft1.play(); 


    Timer messagePrinter = new Timer(); 
    messagePrinter.schedule(new TimerTask() { 

     @Override 
     public void run() { 
      Platform.runLater(() -> { 

       if (!owner.getChildren().contains(added)) 
        return; 

       FadeTransition ft1 = new FadeTransition(Duration.millis(300), added); 
       ft1.setFromValue(1.0); 
       ft1.setToValue(0.0); 
       ft1.play(); 
       ft1.setOnFinished((e) -> { 

        if (owner.getChildren().contains(added)) 
         owner.getChildren().remove(added); 
       }); 

      }); 

     } 
    }, 1000); 
} 

JDK प्रोफाइलर: enter image description here

यह क्योंकि मैं एक स्थिर विधि का उपयोग कर रहा है या मैं इसे अपने आप को नष्ट करना चाहिए है?

उत्तर

7

दरअसल, आपको टाइमर समाप्ति के साथ कोई समस्या नहीं है। प्रोफाइलर में जो थ्रेड आप देखते हैं, वे पहले से ही – को समाप्त कर चुके हैं, उनके पास बाईं ओर एक सफेद बॉक्स है जो इंगित करता है कि वे मर चुके हैं।

प्रोफाइलर प्रोग्राम निष्पादन के दौरान बनाए गए सभी धागे दिखाता है, भले ही वे थ्रेड पहले से ही मर चुके हैं और कचरा इकट्ठा हो।

आप आसानी से पुष्टि कर सकते हैं कि निम्नलिखित कार्य करके: लैम्ब्डा के बजाय, TimerTask का उप-वर्ग बनाएं जो ऐसा ही करेगा और कुछ प्रिंट करने के लिए finalize() विधि को फिर से परिभाषित करेगा। आप देखेंगे कि जब कचरा संग्रह किया जाता है, तो आपके कार्यों को अंतिम रूप दिया जाता है। यह केवल तभी हो सकता है जब थ्रेड बंद हो जाएं, क्योंकि यह Thread कक्षा में एकमात्र जगह है जहां यह Runnable (जो TimerTask उपकरण) के संदर्भ को छोड़ देता है।

यह पुष्टि करने का एक और तरीका है कि तालिका के शीर्ष पर दृश्य ड्रॉपडाउन सूची से 'लाइव थ्रेड' का चयन करना है।

इसके अतिरिक्त, मैं आपको कुछ बेहतर के लिए Timer को प्रतिस्थापित करने की सलाह दूंगा। जब भी आपको कुछ कार्य में देरी की आवश्यकता होती है तो थ्रेड बनाने के लिए यह बहुत अपमानजनक होता है। ScheduledThreadPoolExecutor पर एक नज़र डालें, यह बहुत अधिक अपने कार्य के लिए उपयुक्त लगता है:

// Create a shared executor with a single thread 
private final ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1); 

// Instead of creating a Timer, schedule the task 
executor.schedule(() -> { 
    // Do what you need here 
}, 1, TimeUnit.SECONDS); 

// Don't forget to terminate the scheduler when you don't need it anymore 
scheduler.terminate(); 

यदि आप एक साथ बहुत से अनुसूचित कार्य किया है और उन कार्यों काफी छोटा नहीं हैं निष्पादक को एक से अधिक धागा जोड़ सकते हैं।

+0

मुझे इसके बारे में निश्चित नहीं है लेकिन जानना अच्छा है, वैसे भी, मैंने जावाएफ़एक्स की टाइमलाइन का उपयोग किया जिसके बजाय (कम से कम मेरे लिए) बेहतर है –

2

ऐसा इसलिए है क्योंकि आपको टाइमर मैन्युअल रूप से निपटाने की आवश्यकता है।

यदि आप java.util.Timer का उपयोग करते हैं तो आपको संसाधनों को मुक्त करने के लिए cancel विधि कॉल करने की आवश्यकता है।

+0

क्या आप बता सकते हैं कि कैसे? –

+0

name_of_timer.cancel(); ? –

+0

हां। इस मामले में 'messagePrinter.cancel(); ' – talex

1

आपका टाइमर गैर-डिमन थ्रेड के साथ बनाया गया है, गैर-डिमन थ्रेड आपके प्रोग्राम को समाप्त करने से रोक सकते हैं। आपको टाइमर के लिए कन्स्ट्रक्टर का उपयोग करना चाहिए जो इसे डेमॉन थ्रेड का उपयोग करता है।

boolean daemon=true; Timer messagePrinter = new Timer(daemon);

लेकिन मैं एक ExecutorService का उपयोग करेंगे Andrew Lygin पता चलता है की तरह।

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