अन्य डेवलपर्स को अपना काम पूरा करने के बाद कॉल करने के लिए मजबूर करें


34

जावा 7 में एक पुस्तकालय में, मेरे पास एक वर्ग है जो अन्य वर्गों को सेवाएं प्रदान करता है। इस सेवा वर्ग का एक उदाहरण बनाने के बाद, इसका एक तरीका कई बार कहा जा सकता है (चलो इसे doWork()विधि कहते हैं)। इसलिए मुझे नहीं पता कि सेवा वर्ग का काम कब पूरा होगा।

समस्या यह है कि सेवा वर्ग भारी वस्तुओं का उपयोग करता है और इसे उन्हें छोड़ देना चाहिए। मैंने इस भाग को एक विधि में सेट किया (चलो इसे कॉल करें release()), लेकिन यह गारंटी नहीं है कि अन्य डेवलपर्स इस पद्धति का उपयोग करेंगे।

क्या सेवा वर्ग का कार्य पूरा करने के बाद अन्य डेवलपर्स को इस पद्धति को कॉल करने के लिए बाध्य करने का कोई तरीका है? निश्चित रूप से मैं यह दस्तावेज कर सकता हूं, लेकिन मैं उन्हें मजबूर करना चाहता हूं।

नोट: मैं release()विधि को विधि नहीं कह सकता doWork(), क्योंकि doWork() जब इसे अगले में बुलाया जाता है तो उन वस्तुओं की आवश्यकता होती है।


46
आप जो कर रहे हैं वह अस्थायी युग्मन का एक रूप है और आमतौर पर एक कोड गंध माना जाता है। आप अपने आप को इसके बजाय एक बेहतर डिजाइन के साथ आने के लिए मजबूर करना चाह सकते हैं।
फ्रैंक

1
@ फ्रेंक मैं सहमत हूँ, यदि अंतर्निहित परत का डिज़ाइन बदलना एक विकल्प है तो यह सबसे अच्छा दांव होगा। लेकिन मुझे संदेह है कि यह किसी और की सेवा के आसपास एक आवरण है।
डार ब्रेट

आपकी सेवा को किस प्रकार की भारी वस्तुओं की आवश्यकता है? यदि सेवा वर्ग उन संसाधनों को अपने आप से प्रबंधित करने में सक्षम नहीं होता है (लौकिक युग्मन की आवश्यकता के बिना), तो शायद उन संसाधनों को कहीं और प्रबंधित किया जाए और सेवा को इंजेक्ट किया जाए। क्या आपने सेवा वर्ग के लिए इकाई परीक्षण लिखे हैं?
से आया

18
इसकी आवश्यकता के लिए यह बहुत "अन-जावा" है। जावा कचरा संग्रह के साथ एक भाषा है और अब आप कुछ प्रकार के गर्भनिरोधक के साथ आते हैं, जिसमें आपको डेवलपर्स को "क्लीन अप" करने की आवश्यकता होती है।
पीटर बी

22
@ पीटर क्यों? AutoCloseableइस सटीक उद्देश्य के लिए बनाया गया था।
BgrWorker

जवाबों:


48

व्यावहारिक समाधान वर्ग बनाना है AutoCloseable, और finalize()बैकस्टॉप के रूप में एक विधि प्रदान करना है (यदि उपयुक्त हो ... नीचे देखें)! फिर आप अपनी कक्षा के उपयोगकर्ताओं पर कोशिश-संसाधन के साथ या close()स्पष्ट रूप से कॉल करने के लिए भरोसा करते हैं ।

निश्चित रूप से मैं यह दस्तावेज कर सकता हूं, लेकिन मैं उन्हें मजबूर करना चाहता हूं।

दुर्भाग्य से, वहाँ कोई रास्ता नहीं है 1 जावा में सही काम करने के लिए मजबूर करने के लिए प्रोग्रामर। सबसे अच्छा आप जो करने की उम्मीद कर सकते हैं वह एक स्थिर कोड विश्लेषक में गलत उपयोग करना है।


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

इस प्रकार, यदि आप जिस समस्या को हल करने के लिए बांध रहे हैं, वह उन संसाधनों को पुनः प्राप्त करना है, जिन्हें जल्दी जारी करने की आवश्यकता है , तो आप अंतिम रूप से नाव से चूक गए हैं।

और बस अगर आपको वह नहीं मिला जो मैं ऊपर कह रहा हूं ... तो उत्पादन कोड में अंतिम रूप से उपयोग करना लगभग उचित नहीं है, और आपको कभी भी उन पर भरोसा नहीं करना चाहिए !


1 - तरीके हैं। यदि आप उपयोगकर्ता कोड से सेवा ऑब्जेक्ट को "छिपाने" के लिए तैयार हैं या अपने जीवनचक्र को कसकर नियंत्रित करते हैं (जैसे https://softwareengineering.stackexchange.com/a/345100/172 ) तो उपयोगकर्ता कोड को कॉल करने की आवश्यकता नहीं हैrelease() । हालाँकि, API अधिक जटिल, प्रतिबंधित ... और "बदसूरत" IMO बन जाता है। इसके अलावा, यह प्रोग्रामर को सही काम करने के लिए मजबूर नहीं कर रहा है । यह प्रोग्रामर की गलत काम करने की क्षमता को दूर कर रहा है!


1
फाइनलर्स बहुत बुरा सबक सिखाते हैं - यदि आप इसे खराब कर देते हैं, तो मैं इसे आपके लिए ठीक कर दूँगा। मैं नेट्टी के दृष्टिकोण को प्राथमिकता देता हूं -> एक कॉन्फ़िगरेशन पैरामीटर जो (बाइटबफ़र) फैक्ट्री को निर्देश देता है कि वह बेतरतीब ढंग से X% बाइटबफर्स ​​की संभावना को अंतिम रूप देने के साथ बनाए जो उस स्थान को प्रिंट करता है जहां यह बफर अधिग्रहीत किया गया था (यदि पहले से जारी नहीं है)। इसलिए उत्पादन में इस मान को 0% पर सेट किया जा सकता है - यानी कोई ओवरहेड नहीं, और परीक्षण के दौरान और उत्पाद के रिलीज होने से पहले लीक का पता लगाने के लिए 50% या यहां तक ​​कि 100% जैसे उच्च मूल्य पर
स्वेतलिन ज़ेरेव

11
और याद रखें कि फ़ाइनलिज़र को कभी भी चलाने की गारंटी नहीं है, भले ही ऑब्जेक्ट इंस्टेंस को इकट्ठा किया जा रहा हो!
jwenting

3
यह ध्यान देने योग्य है कि यदि एक AutoCloseable बंद नहीं है, तो ग्रहण एक संकलक चेतावनी का उत्सर्जन करता है। मुझे उम्मीद है कि अन्य जावा आईडीई भी ऐसा करेगा।
मेरिटॉन - हड़ताल पर

1
@jwenting जब ऑब्जेक्ट GC GC होता है तो वे किस स्थिति में नहीं चलते हैं? मुझे यह बताते हुए या समझाते हुए कोई संसाधन नहीं मिला।
सेड्रिक रीचेनबाक

3
@Voo आपने मेरी टिप्पणी को गलत समझा। आपके पास दो कार्यान्वयन हैं -> DefaultResourceऔर FinalizableResourceजो पहले एक को बढ़ाता है और एक अंतिम जोड़ता है। उत्पादन में आप उपयोग करते हैं DefaultResourceजिसमें अंतिम रूप नहीं है-> कोई ओवरहेड नहीं। विकास और परीक्षण के दौरान आप ऐप का उपयोग करने के लिए कॉन्फ़िगर करते हैं FinalizableResourceजिसमें एक अंतिम रूप होता है और इसलिए ओवरहेड जोड़ता है। देव और परीक्षण के दौरान यह एक मुद्दा नहीं है, लेकिन यह आपको उत्पादन तक पहुंचने से पहले लीक की पहचान करने और उन्हें ठीक करने में मदद कर सकता है। फिर भी अगर कोई लीक पीआरडी तक पहुँचता है तो आप लीक FinalizableResourceको आईडी करने के लिए X% बनाने के लिए कारखाने को कॉन्फ़िगर कर सकते हैं
स्वेतलिन ज़ेरेव

55

यह AutoCloseableइंटरफ़ेस के लिए उपयोग-केस और जावा 7 में पेश किए गए try-with-resourcesस्टेटमेंट की तरह लगता है । यदि आपके पास कुछ ऐसा है

public class MyService implements AutoCloseable {
    public void doWork() {
        // ...
    }

    @Override
    public void close() {
        // release resources
    }
}

तब आपके उपभोक्ता इसका उपयोग कर सकते हैं

public class MyConsumer {
    public void foo() {
        try (MyService myService = new MyService()) {
            //...
            myService.doWork()
            //...
            myService.doWork()
            //...
        }
    }
}

और इस बात की releaseपरवाह किए बिना कि उनके कोड को अपवाद फेंकता है या नहीं।


अतिरिक्त जवाब

यदि आप वास्तव में क्या देख रहे हैं, तो यह सुनिश्चित करना है कि कोई भी आपके फ़ंक्शन का उपयोग करने के लिए नहीं भूल सकता है, आपको कुछ चीजें करनी होंगी

  1. सुनिश्चित करें कि सभी निर्माणकर्ता MyServiceनिजी हैं।
  2. उपयोग करने के लिए प्रवेश के एक बिंदु को परिभाषित करें MyServiceजो यह सुनिश्चित करता है कि इसके बाद साफ किया गया है।

आप कुछ ऐसा करेंगे

public interface MyServiceConsumer {
    void accept(MyService value);
}

public class MyService implements AutoCloseable {
    private MyService() {
    }


    public static void useMyService(MyServiceConsumer consumer) {
        try (MyService myService = new MyService()) {
            consumer.accept(myService)
        }
    }
}

आप तब इसका उपयोग करेंगे

public class MyConsumer {
    public void foo() {
        MyService.useMyService(new MyServiceConsumer() {
            public void accept(MyService myService) {
                myService.doWork()
            }
        });
    }
}

मैंने मूल रूप से इस मार्ग की अनुशंसा नहीं की थी क्योंकि यह जावा -8 लैम्ब्डा और कार्यात्मक इंटरफेस (जहां MyServiceConsumerबन जाता है Consumer<MyService>) के बिना छिपा हुआ है और यह आपके उपभोक्ताओं पर काफी थोप रहा है। लेकिन अगर आप केवल यही चाहते हैं कि release()बुलाया जाना चाहिए, तो यह काम करेगा।


1
यह उत्तर शायद मेरी तुलना में बेहतर है। कचरा इकट्ठा करने से पहले मेरे रास्ते में देरी होती है।
डार ब्रेट

1
आप यह कैसे सुनिश्चित करते हैं कि ग्राहक उपयोग करेंगे try-with-resourcesऔर न केवल छोड़ दें try, इस प्रकार closeकॉल गायब है ?
फ्रैंक

@walpen इस तरह से एक ही समस्या है। मैं उपयोगकर्ता को उपयोग करने के लिए कैसे मजबूर कर सकता हूं try-with-resources?
हैशांगफोरियन

1
@Frank / @hasanghaforian, हां, इस तरह से बुलाया जाने के लिए मजबूर नहीं करता है। इसमें परिचितता का लाभ है: जावा डेवलपर्स को पता है कि आपको वास्तव में यह सुनिश्चित करना चाहिए कि .close()कक्षा के क्रियान्वयन को कब बुलाया जाए AutoCloseable
वालपेन

1
क्या आप usingनियतात्मक अंतिमकरण के लिए एक ब्लॉक के साथ एक अंतिम जोड़ी नहीं बना सकते हैं ? कम से कम C # में, यह डेवलपर्स के लिए एक बहुत ही स्पष्ट पैटर्न बन जाता है कि जब लीवरेजिंग संसाधनों को अंतिम निर्धारण की आवश्यकता होती है, तो उपयोग करने की आदत डालें। जब आप किसी को कुछ करने के लिए मजबूर नहीं कर सकते हैं तो कुछ आसान और आदत बनाना अगली सबसे अच्छी बात है। stackoverflow.com/a/2016311/84206
एरोनल्स

52

हाँ तुम कर सकते हो

आप उन्हें जारी करने के लिए पूरी तरह से मजबूर कर सकते हैं, और इसे बना सकते हैं इसलिए इसे भूलना 100% असंभव है, उनके लिए नए Serviceउदाहरण बनाना असंभव है ।

यदि उन्होंने पहले ऐसा कुछ किया है:

Service s = s.new();
try {
  s.doWork("something");
  if (...) s.doWork("something else");
  ...
}
finally {
  s.release(); // oops: easy to forget
}

फिर इसे बदल दें ताकि वे इसे इस तरह एक्सेस करें।

// Their code

Service.runWithRelease(new ServiceConsumer() {
  void run(Service s) {
    s.doWork("something");
    if (...) s.doWork("something else");
    ...
  }  // yay! no s.release() required.
}

// Your code

interface ServiceConsumer {
  void run(Service s);
}

class Service {

   private Service() { ... }      // now: private
   private void release() { ... } // now: private
   public void doWork() { ... }   // unchanged

   public static void runWithRelease(ServiceConsumer consumer) {
      Service s = new Service();
      try {
        consumer.run(s);
      }
      finally {
        s.release();
      } 
    } 
  }

चेतावनियां:

  • इस स्यूडोकोड पर गौर करें, तो यह तब से है जब मैंने जावा लिखा है।
  • इन दिनों के आस-पास अधिक सुरुचिपूर्ण संस्करण हो सकते हैं, हो सकता है कि उस AutoCloseableइंटरफ़ेस का उल्लेख किसी ने किया हो; लेकिन दिए गए उदाहरण को बॉक्स से बाहर काम करना चाहिए, और शिष्टता को छोड़कर (जो अपने आप में एक अच्छा लक्ष्य है) इसे बदलने का कोई बड़ा कारण नहीं होना चाहिए। ध्यान दें कि यह कहने का इरादा है कि आप AutoCloseableअपने निजी कार्यान्वयन के अंदर उपयोग कर सकते हैं ; आपके उपयोगकर्ताओं द्वारा उपयोग किए जाने पर मेरे समाधान का लाभ AutoCloseableयह है कि इसे, फिर से, भुलाया नहीं जा सकता है।
  • उदाहरण के लिए, new Serviceकॉल में तर्कों को इंजेक्ट करने के लिए आपको इसे आवश्यक रूप से मांस देना होगा ।
  • जैसा कि टिप्पणियों में उल्लेख किया गया है, इस तरह का एक निर्माण (यानी, बनाने और नष्ट करने की प्रक्रिया को लेने वाला Service) कॉल करने वाले के हाथ में है या नहीं, इस उत्तर के दायरे से बाहर है। लेकिन अगर आप तय करते हैं कि आपको इसकी आवश्यकता है, तो आप इसे कर सकते हैं।
  • एक टिप्पणीकार ने अपवाद से निपटने के बारे में यह जानकारी प्रदान की: Google पुस्तकें

2
मैं डाउनवोट के लिए टिप्पणियों के बारे में खुश हूं, इसलिए मैं जवाब में सुधार कर सकता हूं।
AnoE

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

30
@ jpmc26, मजेदार मुझे लगता है कि है कि दृष्टिकोण को कम कर देता पर जटिलता और बोझ कॉल उन सब पर संसाधन जीवन चक्र के बारे में सोच से सहेज कर। उसके अलावा; ओपी ने यह नहीं पूछा कि "क्या मुझे उपयोगकर्ताओं को मजबूर करना चाहिए ..." लेकिन "मैं उपयोगकर्ताओं को कैसे मजबूर करूं"। और अगर यह पर्याप्त रूप से महत्वपूर्ण है, तो यह एक समाधान है जो बहुत अच्छी तरह से काम करता है, संरचनात्मक रूप से सरल है (बस इसे एक क्लोजर / रननेबल में लपेटना), यहां तक ​​कि अन्य भाषाओं के लिए हस्तांतरणीय है जिसमें लैम्ब्डा / प्रोक्स / क्लोजर भी हैं। खैर, मैं इसे एसई लोकतंत्र को न्याय करने के लिए छोड़ दूँगा; ओपी ने पहले ही निर्णय लिया है। ;)
AnoE

14
फिर से, @ jpmc26, मैं यह चर्चा करने में ज्यादा दिलचस्पी नहीं रखता कि क्या यह दृष्टिकोण किसी एकल उपयोग के मामले के लिए सही है या नहीं। ओपी पूछता है कि इस तरह की चीज को कैसे लागू किया जाए और यह जवाब बताता है कि ऐसी चीज को कैसे लागू किया जाए । यह तय करना हमारे लिए नहीं है कि पहली जगह में ऐसा करना उचित है या नहीं। दिखाया गया तकनीक एक उपकरण है, अधिक कुछ नहीं, कुछ भी कम नहीं है, और लोगों के बैग-टू-टूल्स में उपयोगी है, मुझे विश्वास है।
AnoE

11
यह सही उत्तर imho है, यह अनिवार्य रूप से छेद-इन-द-मिडिल पैटर्न
jk है।

11

आप कमांड पैटर्न का उपयोग करने का प्रयास कर सकते हैं ।

class MyServiceManager {

    public void execute(MyServiceTask tasks...) {
        // set up everyting
        MyService service = this.acquireService();
        // execute the submitted tasks
        foreach (Task task : tasks)
            task.executeWith(service);
        // cleanup yourself
        service.releaseResources();
    }

}

यह आपको संसाधन अधिग्रहण और रिलीज पर पूर्ण नियंत्रण देता है। कॉलर केवल आपकी सेवा के कार्यों को प्रस्तुत करता है, और आप स्वयं संसाधनों को प्राप्त करने और उनकी सफाई के लिए जिम्मेदार हैं।

हालांकि उसपर पकड़ है। कॉलर अभी भी ऐसा कर सकता है:

MyServiceTask t1 = // some task
manager.execute(t1);
MyServiceTask t2 = // some task
manager.execute(t2);

लेकिन यह समस्या होने पर आप इसे कर सकते हैं। जब प्रदर्शन समस्याएं होती हैं और आपको पता चलता है कि कुछ कॉलर ऐसा करते हैं, तो उन्हें उचित तरीका दिखाएं और समस्या का समाधान करें:

MyServiceTask t1 = // some task
MyServiceTask t2 = // some task
manager.execute(t1, t2);

आप अन्य कार्यों पर निर्भर कार्यों के लिए वादों को लागू करके इस मनमाने ढंग से जटिल बना सकते हैं, लेकिन फिर सामान जारी करना भी अधिक जटिल हो जाता है। यह केवल एक प्रारंभिक बिंदु है।

async

जैसा कि टिप्पणियों में बताया गया है, उपरोक्त वास्तव में अतुल्यकालिक अनुरोधों के साथ काम नहीं करता है। यह सही है। लेकिन यह आसानी से के उपयोग के साथ जावा 8 में हल किया जा सकता CompleteableFuture , विशेष रूप से CompleteableFuture#supplyAsyncअलग-अलग वायदा बनाने के लिए और CompleteableFuture#allOfसंसाधनों की रिहाई perfom करने के लिए एक बार सभी कार्यों को समाप्त कर दिया है। वैकल्पिक रूप से, कोई हमेशा फ्यूचर्स / प्रॉमिस के अपने स्वयं के कार्यान्वयन को रोल करने के लिए थ्रेड्स या एक्सकसोर्से सर्विसेज़ का उपयोग कर सकता है।


1
मैं इसकी सराहना करूंगा यदि डाउनवोटर्स एक टिप्पणी छोड़ते हैं कि उन्हें क्यों लगता है कि यह बुरा है, ताकि मैं या तो उन चिंताओं को सीधे स्वीकार कर सकूं या कम से कम भविष्य के लिए एक और दृष्टिकोण प्राप्त कर सकूं। धन्यवाद!
पॉलीग्नोमे

+1 अपवोट। यह एक दृष्टिकोण हो सकता है, लेकिन सेवा async है और उपभोक्ता को अगली सेवा के लिए पूछने से पहले पहला परिणाम प्राप्त करना होगा।
हैशांगफोरियन

1
यह सिर्फ एक नंगेपन का खाका है। जेएस वादों के साथ इसे हल करता है, आप वायदा और एक कलेक्टर के साथ जावा में समान काम कर सकते हैं जिसे कहा जाता है जब सभी कार्य समाप्त हो जाते हैं और फिर साफ हो जाते हैं। यह निश्चित रूप से async और यहां तक ​​कि निर्भरता प्राप्त करने के लिए संभव है, लेकिन यह भी चीजों को बहुत जटिल करता है।
पॉलीग्नोमे

3

यदि आप कर सकते हैं, तो उपयोगकर्ता को संसाधन बनाने की अनुमति न दें। उपयोगकर्ता को आपकी विधि में विज़िटर ऑब्जेक्ट पास करने दें, जो संसाधन बनाएगा, उसे विज़िटर ऑब्जेक्ट की विधि में पास करेगा, और बाद में रिलीज़ करेगा।


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

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

1

मेरा विचार पॉलीग्नोम के समान था।

आपकी कक्षा में "do_something ()" विधियाँ हो सकती हैं, बस एक निजी कमांड सूची में कमांड जोड़ सकते हैं। फिर, एक "प्रतिबद्ध ()" विधि है जो वास्तव में काम करता है, और "रिलीज ()" कहता है।

इसलिए, यदि उपयोगकर्ता कभी भी कॉल नहीं करता है (), तो काम कभी नहीं किया जाता है। यदि वे करते हैं, तो संसाधनों को मुक्त कर दिया जाता है।

public class Foo
{
  private ArrayList<ICommand> _commands;

  public Foo doSomething(int arg) { _commands.Add(new DoSomethingCommand(arg)); return this; }
  public Foo doSomethingElse() { _commands.Add(new DoSomethingElseCommand()); return this; }

  public void commit() { 
     for(ICommand c : _commands) c.doWork();
     release();
     _commands.clear();
  }

}

फिर आप इसे foo.doSomething.doSomethineElse ()। प्रतिबद्ध ();


यह एक ही समाधान है, लेकिन कॉल करने वाले को कार्य सूची को बनाए रखने के लिए कहने के बजाय आप इसे आंतरिक रूप से बनाए रखते हैं। मूल अवधारणा वस्तुतः एक ही है। लेकिन यह जावा मैंने कभी देखा है के लिए किसी भी कोडिंग सम्मेलनों का पालन नहीं करता है और वास्तव में पढ़ने के लिए काफी कठिन है (लूप हेडर के रूप में एक ही लाइन पर बॉडी, शुरुआत में _)।
पॉलिनेग्न

हाँ, यह कमांड पैटर्न है। मैं बस कुछ कोड नीचे रख रहा हूं, जो मैं सोच रहा था कि जितना संभव हो सके उतना संक्षिप्त रूप दें। मैं ज्यादातर इन दिनों C # लिखता हूं, जहां प्रायः निजी चर _ के साथ उपसर्ग किया जाता है।
सावा बी।

-1

उल्लिखित लोगों के लिए एक अन्य विकल्प "स्मार्ट संदर्भ" का उपयोग होगा, जो आपके इनकैप्सुलेटेड संसाधनों को एक तरह से प्रबंधित करने के लिए है, जो कचरा संग्रहकर्ता को मैन्युअल रूप से मुक्त संसाधनों के बिना स्वचालित रूप से साफ करने में सक्षम बनाता है। उनकी उपयोगिता आपके कार्यान्वयन पर निश्चित रूप से निर्भर करती है। इस अद्भुत ब्लॉग पोस्ट में इस विषय पर और अधिक पढ़ें: https://community.oracle.com/blogs/enicholas/2006/05/04/understanding-weak-references


यह एक दिलचस्प विचार है, लेकिन मैं यह नहीं देख सकता कि कैसे कमजोर संदर्भों का उपयोग करने से ओपी की समस्या हल हो जाती है। सेवा वर्ग को यह नहीं पता है कि क्या यह एक और doWork () अनुरोध प्राप्त करने जा रहा है। यदि यह अपने भारी वस्तुओं के संदर्भ को जारी करता है, और फिर इसे एक और doWork () कॉल मिलता है, तो यह विफल हो जाएगा।
जे एलस्टन

-4

किसी भी अन्य कक्षा उन्मुख भाषा के लिए, मैं इसे विध्वंसक में डालूँगा, लेकिन चूंकि यह एक विकल्प नहीं है, मुझे लगता है कि आप अंतिम विधि को ओवरराइड कर सकते हैं। इस तरह जब उदाहरण दायरे से बाहर हो जाता है और कचरा एकत्र किया जाता है तो इसे जारी किया जाएगा।

@Override
public void finalize() {
    this.release();
}

मैं जावा से बहुत परिचित नहीं हूं, लेकिन मुझे लगता है कि यही वह उद्देश्य है जिसके लिए अंतिम रूप देना है ()।

http://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#finalize ()


7
स्टीफन ने अपने जवाब में कारण के लिए समस्या का यह एक बुरा समाधान है -If you rely on finalizers to tidy up, you run into the problem that it can take a very long time for the tidy-up to happen. The finalizer will only be run after the GC decides that the object is no longer reachable. That may not happen until the JVM does a full collection.
डेनेथ

4
और फिर भी finalizer वास्तव में नहीं चला सकते हैं ...
jwenting

3
फ़ाइनलीज़र कुख्यात हैं: वे भाग सकते हैं, वे कभी नहीं चल सकते हैं, अगर वे चलाते हैं तो वे कब दौड़ेंगे इसकी कोई गारंटी नहीं है । यहां तक ​​कि जोश बलोच जैसे जावा आर्किटेक्ट भी कहते हैं कि अंतिम विचार एक भयानक विचार हैं (संदर्भ: प्रभावी जावा (दूसरा संस्करण) )।

इस तरह के मुद्दे मुझे अपने नियतिवादी विनाश और RAII के साथ C ++ की याद दिलाते हैं ...
मार्क के कोवान
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.