2012-01-26 7 views
14

मैं InheritableThreadLocal और ThreadPoolExecutor दोनों का उपयोग करने का प्रयास कर रहा हूं।ThreadPoolExecutor के साथ इनहेरटेबल थ्रेडलोकल का उपयोग करना - या - एक थ्रेडपूलएक्सएटर जो थ्रेड का पुन: उपयोग नहीं करता है

यह टूट जाता है क्योंकि ThreadPoolExecutor प्रत्येक पूल के लिए धागे का उपयोग करता है (यह एक पूल है, सब के बाद), जिसका अर्थ है InheritableThreadLocal अपेक्षित काम नहीं करता है। अब समस्या मेरे लिए स्पष्ट प्रतीत होती है, लेकिन यह ट्रैक करने के लिए विशेष रूप से अस्पष्ट था।

मैं InheritableThreadLocal का उपयोग करता हूं ताकि कई शीर्ष-स्तरीय प्रक्रियाओं में से प्रत्येक के लिए अपना स्वयं का डेटाबेस कनेक्शन हो और यह उप-प्रक्रियाएं उत्पन्न हो जाएं। मैं सिर्फ एक साझा कनेक्शन पूल का उपयोग नहीं करता क्योंकि प्रत्येक शीर्ष-स्तरीय प्रक्रिया डेटाबेस से पहले और/या तैयार किए गए बहुत से तैयार किए गए स्टार्टमेंट तैयार करने से पहले इसके कनेक्शन के साथ बहुत से बहु-चरण कार्य करेगी।

मैं इन शीर्ष-स्तरीय प्रक्रियाओं के बीच साझा ThreadPoolExecutor का उपयोग करता हूं क्योंकि कुछ व्यवहार हैं जिन्हें गेट करने की आवश्यकता है। जैसे भले ही मेरे पास 4 शीर्ष-स्तरीय प्रक्रियाएं चल रही हों, मेरे पास एक समय में डेटाबेस में कोई भी प्रक्रिया लिख ​​सकती है (या सिस्टम को किसी अन्य साझा संसाधन पर गेट की आवश्यकता है)। तो मेरे पास शीर्ष-स्तरीय प्रक्रिया Runnable बनाएगी और यह सुनिश्चित करने के लिए साझा की गई ThreadPoolExecutor पर भेज दी जाएगी कि पूरे सिस्टम में एक से अधिक (या दो या तीन मामले हो सकते हैं) एक ही समय में चल रहे हैं।

समस्या यह है कि ThreadPoolExecutor पूल के लिए अपने धागे का पुन: उपयोग करता है, InheritableThreadLocal उस पूल में चलने वाले मूल मान को उठा रहा है जो शीर्ष-स्तरीय प्रक्रिया में मौजूद मान के बजाए उस पूल में चलाया गया था जो रननेबल को भेजा गया था ThreadPoolExecutor

  • वहाँ InheritableThreadLocal मूल्य है कि प्रक्रिया है जिसके बल्कि पुन: उपयोग किया थ्रेड पूल के संदर्भ से Runnable बनाया के संदर्भ में था का उपयोग करने के ThreadPoolExecutor में कार्यकर्ता पूल मजबूर करने के लिए कोई तरीका है?

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

  • क्या कोई अन्य समाधान या सुझाव है जो मैंने ऊपर वर्णित किए गए कार्यों को पूरा करने के लिए किया है?

(जबकि मुझे पता है मैं समुदाय साइकिल के कुछ प्रकार की तरह subthread को subthread के वर्ग के लिए कक्षा से डेटाबेस कनेक्शन के आसपास पारित करके समस्या का समाधान हो सकता है, मैं इस से बचने के लिए चाहते हैं।)

StackOverflow, InheritableThreadLocal and thread pools पर एक पिछला प्रश्न है, जो इस समस्या को भी संबोधित करता है। हालांकि, उस समस्या का समाधान यह प्रतीत होता है कि यह इनहेरटेबल थ्रेडलोकल के लिए एक खराब उपयोग केस है, जो मुझे नहीं लगता कि मेरी स्थिति पर लागू होता है।

किसी भी विचार के लिए धन्यवाद।

उत्तर

5

साझा संसाधनों की सुरक्षा के लिए ThreadPoolExecutor का उपयोग करने के बजाय, java.util.concurrent.Semaphore का उपयोग क्यों न करें? आपके द्वारा बनाए गए उप कार्यों को अपने स्वयं के धागे में पूरा करने के लिए चलाया जाएगा, लेकिन सेमाफोर से परमिट प्राप्त करने के बाद, और निश्चित रूप से परमिट जारी करने के बाद ही।

+0

मैंने सेमाफोर का उपयोग नहीं किया है, इसलिए मैं इसे देख लूंगा। हम निष्पादकों (फ्यूचर्स, टाइमआउट इत्यादि) की कई अन्य विशेषताओं का उपयोग करते हैं, लेकिन यह संभव है कि मैं सेमफोरस के साथ ऐसा कर सकूं या मैं नियमित रूप से निष्पादक (थ्रेड पूल नहीं) का उपयोग कर सकता हूं ताकि सब कुछ प्राप्त करने के लिए सेमफोरों के साथ। धन्यवाद। –

+0

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

0

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

+0

क्या आप इस बारे में कुछ और जानकारी प्रदान कर सकते हैं कि आपने यह कैसे किया? –

+0

क्या 'थ्रेडलोकल कॉन्टेक्स्ट माइग्रेटर.जावा' कहीं सार्वजनिक रूप से उपलब्ध है? –

3

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

रननेबल के रूप में सहयोगी w/एक संदर्भ के रूप में। ExecutorPool के सार्वजनिक void execute(Runnable command) ओवरराइड करें और Runnable को InheritedThreadLocal से पहले स्थान पर ले जाने वाले मान को लेकर कुछ संदर्भ के साथ लपेटें।

रैपिंग वर्ग

class WrappedRunnable extends Runnable{ 
    static final ThreadLocal<Ctx> context=new ThreadLocal<Ctx>(); 
    final Runnable target; 
    final Ctx context; 
    WrappedRunnable(Ctx context, Runnable target){...} 

    public void run(){ 
    ctx.set(context); 
    try{ 
     target.run(); 
    }finally{ 
     ctx.set(null);//or ctx.remove() 
    } 
    } 
} 

वैकल्पिक रूप से कुछ इस प्रकार दिखाई देगा, वहाँ है कि एक नया बनाता है ThreadPoolExecutor के किसी भी कार्यान्वयन है> जो हर बार किसी नए Runnable शुरू होता है थ्रेड? मेरे उद्देश्यों के लिए मैं केवल एक निश्चित आकार में एक साथ चलने वाले धागे की संख्या को गेट करने की परवाह करता हूं।

जबकि देखने के प्रदर्शन बिंदु से सही मायने में बुरा है, आप अपने खुद के लागू कर सकते हैं, मूल रूप से आप Executor कि नया थ्रेड spawns और यह शुरू होता है के लिए केवल execute(Runnable task) विधि की जरूरत है।

+0

आप क्या कहते हैं कि इनहेरिएबल थ्रेडलोकल रिसाव प्रवण है? मैं इसके बारे में गुगल रहा हूं और कोई लेख या उदाहरण नहीं देख रहा हूं जहां यह स्मृति रिसाव का कारण बनता है। क्या आप मुझे कुछ स्रोतों पर इंगित कर सकते हैं? –

+0

@ जेफगोल्डबर्ग, ठीक है, मुझे अच्छी तरह से पता है कि यह कैसे कार्यान्वित किया गया है और मैं बहुत सारे बुनियादी ढांचे/मिडलवेयर करता हूं। थ्रेडलोकल रिसाव प्रवण है और विरासत संस्करण बहुत रिसाव प्रवण है। वस्तुतः आप नियंत्रण नहीं कर सकते जब किसी भी कारण से एक नया धागा पैदा होता है (जेडीके स्वयं करता है)। एक लंबा चलने वाला धागा मूल्य और उसके क्लासलोडर को रिसाव करेगा और उस दूरदराज के धागे को अन्यथा बेकार वस्तु के संदर्भ में रखने से रोकने का कोई तरीका नहीं है। 'childValue' मामले को संशोधित कर सकता है लेकिन इसे एक थ्रेड में बुलाया जाता है जो इसे रखता है, और नया लक्ष्य धागा अज्ञात है ... – bestsss

+0

एक त्वरित नोट: इस दृष्टिकोण ने काम किया। मैं @ चालीस-दो से सलाह ले रहा हूं और इसके बजाय दृष्टिकोण बदल रहा हूं, अन्यथा मैं इसे उत्तर के रूप में चुना होगा। सलाह और मदद के लिए धन्यवाद। –

0

क्यों मुख्य कार्य द्वारा उत्पन्न किसी भी उप-कार्यों पर वर्तमान कनेक्शन को पास न करें? शायद कुछ प्रकार के साझा संदर्भ वस्तु?

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