2012-09-14 11 views
13

जब एक ThreadLocal का उपयोग कर मैं हमेशा remove() बुलाना चाहिए जब मैंने किया हूँ या जब मैं set कर पुराने मूल्य वैसे भी बदल दिया जाता है तो remove बेमानी है?थ्रेडलोकल हटा दें?

उत्तर

12

set हमेशा पुराने मूल्य बदल देता है।

इस के लिए

  • Calendar.set() और Date.set()
  • BitSet.set()
  • List.set()
  • setters
सच है

आप बिना निकालना मतलब यह GCed नहीं हो जाएगा?

थ्रेड मरने तक इसे हटाया नहीं जाएगा। यह आप को दूर बुला बिना आप पर गायब नहीं होगा()

क्या यह एक स्मृति रिसाव है या नहीं अपने कार्यक्रम पर निर्भर करता है। आपको बड़े थ्रेड स्थानीय ऑब्जेक्ट्स के साथ बहुत सारे धागे बनाना होगा जिन्हें आपको किसी मामले के लिए जरूरी नहीं है। जैसे 1 केबी ऑब्जेक्ट वाले 1000 धागे 1 एमबी तक बर्बाद हो सकते हैं, लेकिन यदि आप इस तरह की चीज कर रहे हैं तो यह एक डिज़ाइन समस्या का सुझाव देता है।


एकमात्र जगह आपको स्मृति रिसाव मिल सकती है।

for (int i = 0; ; i++) { 
    // don't subclass Thread. 
    new Thread() { 
     // this is somewhat pointless as you are defining a ThreadLocal per thread. 
     final ThreadLocal<Object> tlObject = new ThreadLocal<Object>() { 
     }; 

     public void run() { 
      tlObject.set(new byte[8 * 1024 * 1024]); 
     } 
    }.start(); 
    Thread.sleep(1); 
    if (i % 1000 == 0) { 
     System.gc(); 
     System.out.println(i); 
    } 
} 
-verbosegc प्रिंट के साथ

[Full GC 213548K->49484K(3832192K), 0.0334194 secs] 
39000 
[GC 2786060K->82412K(3836864K), 0.0132035 secs] 
[GC 2815569K->107052K(3836544K), 0.0212252 secs] 
[GC 2836162K->131628K(3837824K), 0.0199268 secs] 
[GC 2867613K->156204K(3837568K), 0.0209828 secs] 
[GC 2886894K->180780K(3838272K), 0.0191244 secs] 
[GC 2911942K->205356K(3838080K), 0.0187482 secs] 
[GC 421535K->229932K(3838208K), 0.0192605 secs] 
[Full GC 229932K->49484K(3838208K), 0.0344509 secs] 
40000 

नोट: एक पूर्ण जीसी के बाद आकार में एक ही 49484K

ऊपर मामले में आप एक ThreadLocal जो धागा जो ThreadLocal को संदर्भित करता है को संदर्भित करता होगा। हालांकि, चूंकि थ्रेड मर चुका है क्योंकि यह स्मृति रिसाव का कारण नहीं बनता है क्योंकि यह ए -> बी और बी -> ए

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

+1

एमआईटीडी बताते हुए स्मृति रिसाव के बारे में क्या? – Jim

+0

@Jim अच्छा सवाल, एक उत्तर जोड़ा है। –

+0

पीटर, लीक विस्तारित थ्रेडलोकल्स पर हो सकता है क्योंकि धागा संदर्भ रखने जा रहा है। अनावश्यक और गतिशील वर्गीकरण के बारे में सोचें। – bestsss

3

set: निर्दिष्ट मूल्य को यह धागा स्थानीय चर की वर्तमान धागा की प्रतिलिपि सेट करता है।

मतलब जो कुछ भी है कि स्मृति स्थान में था, अब तक ओवरराइट किया जाएगा क्या आप set

13

के माध्यम से पारित क्योंकि ThreadLocal है currentThread और value की Map, अब उपयोग कर रहा था जो अगर आप सूत्र में मूल्य नहीं निकालते हैं यह फिर एक स्मृति रिसाव पैदा करेगा।

तुम हमेशा हटाने क्योंकि ThreadLocal वर्ग थ्रेड कक्षा ThreadLocal द्वारा परिभाषित से मूल्यों डालता फोन करना चाहिए।मूल्य स्थानीय मूल्य; इससे थ्रेड और संबंधित ऑब्जेक्ट्स का संदर्भ भी हो सकता है।

ThreadLocal

मूल्य के स्रोत कोड से शून्य पर सेट हो जाएगा और अंतर्निहित प्रविष्टि अभी भी मौजूद रहेंगे।

+0

आपका मतलब है 'हटाएं' के बिना यह जीसीड नहीं होगा? – Jim

+1

यह मान के बारे में नहीं है कि यह 'थ्रेड' के बारे में है, जिसमें 'थ्रेडलोकल' में संदर्भ है यदि आप इसे कॉल नहीं करते हैं तो इसे कभी भी जीसीड नहीं मिलेगा। –

1

तो चर आप remove की कोशिश कर रहे हो जाएगा हमेशा set धागा की अगली फांसी में, मैं इसे हटाने के बारे में चिंता नहीं करता। set इसके मूल्य को ओवरराइट करेगा।

लेकिन यदि आप केवल कुछ सर्कसमैंटेंस (उदाहरण के लिए, केवल एक विशिष्ट प्रकार के अनुरोधों का इलाज करते समय) उस चर को सेट कर रहे हैं, तो इसे हटाने के लिए सुविधाजनक हो सकता है ताकि यह आसपास न रहे, उदाहरण के लिए, थ्रेड पूल में वापस रखा गया है। आप किसी भी कारण उपयोग remove() के लिए ThreadLocal का विस्तार तो :

1

मैं इसे सरल कर देगा। वेनिला थ्रेडलोकल पर set(null) का उपयोग करें। मूल रूप से ThreadLocal.remove() का उपयोग नहीं पर एक बढ़ाया ThreadLocal मेमोरी लीक (classloader वाले सबसे अधिक संभावना)

आपको और अधिक जानकारी क्यों, एक टिप्पणी पोस्ट की जरूरत है हो सकता है।

+0

मुझे 'सेट (शून्य)' और 'निकालें' की आपकी भिन्नता को समझ में नहीं आता है। क्या मुझे 'सेट' कॉल करने से पहले 'सेट (शून्य)' कॉल करना चाहिए? इससे रिसाव क्यों होगा? – Jim

+0

@bestsss दिलचस्प भेद। – irreputable

+0

@Jim, ऑब्जेक्ट को 'सेट (नल)' या 'निकालें()' के माध्यम से नहीं हटा रहा है और धागा चल रहा है, यह चीज रिसाव के कारण होगी।सेट (xxx) से पहले सेट को कॉल करने की बिल्कुल आवश्यकता नहीं है। – bestsss

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