2010-01-04 15 views
14

क्या थ्रेडलोकल्स को थ्रेड से बांधने का कोई तरीका है? आदर्श रूप में मैं थ्रेड। थ्रेडलोकल्स मानचित्र तक पहुंच सकता हूं, लेकिन यह पैकेज सुरक्षित है।जावा: सूची धागे स्थानीय?

मुझे इसकी आवश्यकता है क्योंकि मुझे धागे का निरीक्षण करने की आवश्यकता है क्योंकि थ्रेडलोकल्स को ठीक से साफ करने के लिए उन्हें थ्रेड पूल में वापस कर दिया गया है। शायद ऐसा करने का दूसरा तरीका है?

उत्तर

2

आप जो भी सफाई चाहते हैं, उसे साफ करने के लिए थ्रेड पूल की afterExecute विधि का उपयोग कर सकते हैं, जब तक आप जानते हैं कि आप कौन से चर साफ़ करना चाहते हैं। धागा भीतर से, वर्ग (ते) आप में रुचि के घोषित क्षेत्रों के माध्यम से पुनरावृति, और हर एक जिसका प्रकार के लिए, set अपने initialValue को वस्तु पर ThreadLocal का एक उदाहरण है यह -

नहीं तो आप प्रतिबिंब इस्तेमाल कर सकते हैं (एस) आप की परवाह है।

1

मुझे इसकी आवश्यकता है क्योंकि मुझे धागे का निरीक्षण करने की आवश्यकता है क्योंकि थ्रेडलोकल्स को ठीक तरह से साफ किया गया है ताकि यह सुनिश्चित किया जा सके।

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

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

+4

सहमत हुए। लेकिन मैं मौजूदा कोड में एक बग को ठीक करना चाहता हूं, इसे फिर से आर्किटेक्ट नहीं करना चाहता हूं। –

0

आप एओपी-जैसे निर्माण का उपयोग कर सकते हैं, एक रननेबल कार्यान्वयन जो आपके द्वारा कार्यान्वित करके मूल रननेबल को लपेटता है। यह मूल रननेबल की रन विधि का आह्वान करेगा और उसके बाद थ्रेड के संदर्भ में आपको आवश्यक कोई भी अन्य क्लीनअप निष्पादित करेगा, जो आपको ThreadLocal.remove() विधि को कॉल करने की अनुमति देगा। फिर, इस रैपर को थ्रेड पूल में दें। यह किसी भी थ्रेड पूल कार्यान्वयन के लिए काम करेगा (उदाहरण के लिए पहले/बाद में बिना विधियों के 0)

+0

थ्रेड लाइफसाइकिल में हुकिंग समस्या नहीं है। मैं ThreadPoolExecutor का उपयोग कर रहा हूं, इसलिए मेरे पास काम करने के बाद एक्सेक्यूट विधि है। समस्या को धागा दिया जाता है, मैं थ्रेड स्थानीय भंडारण की गणना कैसे करूं? मैं यह देखना चाहता हूं कि यह खाली है, और यदि कोई चेतावनी लॉग नहीं है। –

+0

क्या आपके पास थ्रेड स्थानीय उपयोग पर नियंत्रण है (क्या आप डेवलपर्स को अपने कार्यान्वयन का उपयोग करने के लिए कह सकते हैं)? आप अपने लक्ष्य को प्राप्त करने में सहायता के लिए थ्रेडलोकल का विस्तार करने में सक्षम हो सकते हैं। – Armadillo

0

स्रोतों से, यह बहुत तंग दिखता है। सब कुछ थ्रेड या थ्रेडलोकल के लिए निजी है।

थ्रेडलोकल को फिर से परिभाषित करके एक उपकरण एजेंट के माध्यम से आपको जो कुछ चाहिए, वह करने के लिए सक्षम हो सकता है जो स्थानीय थ्रेड पर स्थानीय लोगों को डंप करेगा। http://today.java.net/pub/a/today/2008/04/24/add-logging-at-class-load-time-with-instrumentation.html

आप विधि जोड़ने का ThreadLocal बाईटकोड पैच करने के लिए BCEL या JavaAssist का उपयोग करना होगा:

यहाँ एक उदाहरण मैं एक मौजूदा वर्ग के लिए प्रवेश जोड़ने के लिए मिला है। बाद में, आपको विधि में हैंडल प्राप्त करने के लिए प्रतिबिंब का उपयोग करने की आवश्यकता होगी ताकि आप इसे कॉल कर सकें।

नोट: यदि आप प्रतिबंधित वातावरण (एप्लेट या ऐससेवर) में चल रहे हैं तो यह शायद काम नहीं करेगा क्योंकि सुरक्षा तंत्र आमतौर पर आपको सिस्टम कक्षाओं के बारे में सोचने से रोकते हैं।

10

Listing ThreadLocals और Clearing ThreadLocals जेवीएम की सामान्य अनुमतियों को ओवरराइड करने के लिए प्रतिबिंब (और the setAccessible() flag) का उपयोग करके पूरा किया जा सकता है। स्पष्ट कारणों से, यह तब उपलब्ध नहीं है जब सभी सुरक्षा तंत्र मौजूद हों।

2

'ऐसा करने का एक और अच्छा तरीका' की रेखाओं के साथ, मैंने एक रननेबल रैपर बनाया जो पूर्व-मौजूदा थ्रेड लोकल का एक स्नैपशॉट लेता है, घोंसला चलाने योग्य चलाता है, फिर किसी थ्रेड लोकल को साफ़ करता है (शून्य पर सेट करता है) शुरुआत में उपस्थित नहीं था।

यह 'स्नैपशॉट' कोड को उप-वर्गीकृत निष्पादक के पहले एक्सेक्यूट() और 'क्लीनअप' कोड में @danben द्वारा सुझाए गए अनुसार 'क्लीनअप' कोड में डालकर बेहतर किया जा सकता है।

किसी भी तरह से, सौंदर्य यह है कि आपको कठोर कोड नहीं है जो थ्रेड स्थानीय को रखने या त्यागने के लिए नहीं है।

अव्यवस्था से निपटने के लिए स्रोत सूची से अपवाद हैंडलिंग हटा दी गई थी।

 
public class ThreadLocalCleaningRunnable implements Runnable 
{ 
    private final Runnable runnable; 

    public ThreadLocalCleaningRunnable(Runnable runnable) { 
     this.runnable = nonNull(runnable); 
    } 

    public void run() { 
    // printThreadLocals(); 
     Set> initialThreadLocalKeys = getThreadLocalKeys(); 
     try { 
      runnable.run(); 
     } 
     finally { 
      cleanThreadLocalsExcept(initialThreadLocalKeys); 
     // printThreadLocals(); 
     } 
    } 

    public static void printThreadLocals() { 
     Thread thread = Thread.currentThread(); 

      Field threadLocalsField = Thread.class.getDeclaredField("threadLocals"); 
      threadLocalsField.setAccessible(true); 
      Class threadLocalMapKlazz = Class.forName("java.lang.ThreadLocal$ThreadLocalMap"); 
      Field tableField = threadLocalMapKlazz.getDeclaredField("table"); 
      tableField.setAccessible(true); 

      Object threadLocals = threadLocalsField.get(thread); 
      if (threadLocals != null) { 
       Object table = tableField.get(threadLocals); 
       if (table != null) { 
        int threadLocalCount = Array.getLength(table); 
        String threadName = thread.getName(); 

        for (int i = 0; i > getThreadLocalKeys() { 
     Thread thread = Thread.currentThread(); 

      Set> threadLocalKeys = new HashSet>(); 

      Field threadLocalsField = Thread.class.getDeclaredField("threadLocals"); 
      threadLocalsField.setAccessible(true); 
      Class threadLocalMapKlazz = Class.forName("java.lang.ThreadLocal$ThreadLocalMap"); 
      Field tableField = threadLocalMapKlazz.getDeclaredField("table"); 
      tableField.setAccessible(true); 

      Object threadLocals = threadLocalsField.get(thread); 
      if (threadLocals != null) { 
       Object table = tableField.get(threadLocals); 
       if (table != null) { 
        int threadLocalCount = Array.getLength(table); 

        for (int i = 0; i) entry).get(); 
          if (o instanceof ThreadLocal) { 
           threadLocalKeys.add((ThreadLocal) o); 
          } 
         } 
        } 
       } 
      } 
      return threadLocalKeys; 
    } 

    public static void cleanThreadLocalsExcept(Set> keptThreadLocalKeys) { 
     Thread thread = Thread.currentThread(); 

      Field threadLocalsField = Thread.class.getDeclaredField("threadLocals"); 
      threadLocalsField.setAccessible(true); 
      Class threadLocalMapKlazz = Class.forName("java.lang.ThreadLocal$ThreadLocalMap"); 
      Field tableField = threadLocalMapKlazz.getDeclaredField("table"); 
      tableField.setAccessible(true); 

      Object threadLocals = threadLocalsField.get(thread); 
      if (threadLocals != null) { 
       Object table = tableField.get(threadLocals); 
       if (table != null) { 
        int threadLocalCount = Array.getLength(table); 

        for (int i = 0; i) entry).get(); 
          if (o instanceof ThreadLocal) { 
           ThreadLocal tl = (ThreadLocal) o; 
           if (!keptThreadLocalKeys.contains(tl)) { 
            Field valueField = entry.getClass().getDeclaredField("value"); 
            valueField.setAccessible(true); 
            valueField.set(entry, null); 
           } 
          } 
         } 
        } 
       } 
      } 
    } 
} 

+0

बीटीडब्ल्यू, मेरी ज़रूरत एक थ्रेड पूल में एचटीएमएल यूनिट (या सेलेनियम हेडलेस) का उपयोग करने के लिए थी जो थ्रेड स्थानीय मेमोरी लीक से भी पीड़ित है। – karmakaze

+0

कोड संकलित नहीं करता है। – mrswadge

+0

कोड पर एचटीएमएल स्वच्छता ने इसे थोड़ा गड़बड़ कर दिया है। सामान्य प्रकार और कोण ब्रैकेट के आसपास वर्ण गायब हैं। इसका अधिकांश अनुमान लगाया जा सकता है। मैं देखूंगा कि क्या मैं इस स्रोत को फिर से ढूंढ सकता हूं और अपडेट कर सकता हूं। – karmakaze

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