2012-10-10 15 views
8

चुनते समय नए चैनल को सही तरीके से पंजीकृत कैसे करें मेरे पास Thread एक निजी Selector और सार्वजनिक register(SelectableChannel channel, ...) विधि है जो अन्य धागे चयनकर्ता को चैनल पंजीकृत करने की अनुमति देता है।एनआईओ चयनकर्ता:

के रूप में के दौरान here, चैनल का register() ब्लॉक जवाब चयनकर्ता के select()/select(long timeout) तो हम चयनकर्ता wakeup() की जरूरत है।

मेरा धागा अनिश्चित काल तक चुनता है (जब तक कि यह बाधित न हो) और यह वास्तव में चैनल के register() कहने से पहले अगले चयन में शामिल होने का प्रबंधन करता है। तो मैंने सोचा कि register() पहले होता है यह सुनिश्चित करने के लिए कि मैं synchronized ब्लॉक के साथ एक साधारण लॉक का उपयोग करता हूं।

कोड: इससे पहले कि धागा अगले चयन पाश के साथ जारी है (अप्रासंगिक कोड पठनीयता के लिए हटाया)

public class SelectorThread extends Thread { 
    ... 

    public void register(SelectableChannel channel, Attachment attachment) throws IOException { 
    channel.configureBlocking(false); 
    synchronized (this) { // LOCKING OCCURS HERE 
     selector.wakeup(); 
     channel.register(selector, 
         SelectionKey.OP_READ, 
         attachment); 
    } 
    } 

    @Override 
    public void run() { 
    int ready; 
    Set<SelectionKey> readyKeys; 
    while (!isInterrupted()) { 
     synchronized (this) {} // LOCKING OCCURS HERE 

     try { 
     ready = selector.select(5000); 
     } catch (IOException e) { 
     e.printStackTrace(); 
     continue; 
     } 

     if (ready == 0) { 
     continue; 
     } 

     readyKeys = selector.selectedKeys(); 

     for (SelectionKey key : readyKeys) { 
     readyKeys.remove(key); 

     if (!key.isValid()) { 
      continue; 
     } 

     if (key.isReadable()) { 
      ... 
     } 
     } 
    } 
    } 
} 

यह सरल ताला अनुमति देता है register() होने की। जहां तक ​​मैंने परीक्षण किया, यह माना जाता है कि यह काम करता है।

प्रश्न: क्या यह करने के लिए "अच्छा" तरीका है या क्या कोई गंभीर डाउनसाइड्स है? पंजीकरण के लिए चैनल स्टोर करने के लिए सूची या कतार (जैसा कि here सुझाया गया है) का उपयोग करना बेहतर होगा, या इसके बजाय this जैसे अधिक परिष्कृत लॉक का उपयोग करना बेहतर होगा? उस के पेशेवर/विपक्ष क्या होंगे? या क्या कोई "बेहतर" तरीके हैं?

+0

चुनिंदा() को चुनने के दौरान चयनकर्ता के साथ चैनल पंजीकृत करते समय [जावा थ्रेड ब्लॉक का संभावित डुप्लिकेट) कहा जाता है। क्या करना है?] (Https://stackoverflow.com/questions/1057224/java-thread-blocks-while-registering-channel-with-selector-while-select-is-cal) – Flow

उत्तर

3

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

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

व्यक्तिगत रूप से, मुझे कतार तकनीक पसंद है। वे इस तरह से एक मास्टर और श्रमिकों की तरह, अपने धागे के लिए भूमिका नियुक्त करते हैं।जबकि मास्टर पर सभी प्रकार के नियंत्रण होते हैं, जैसे किसी कतार से अधिक पंजीकरण के लिए प्रत्येक चयन जांच के बाद, किसी भी पढ़े गए कार्यों को स्पष्ट और खेत करें, हैंडलर समग्र कनेक्शन सेटअप (डिस्कनेक्ट आदि) में कोई भी परिवर्तन ... "बीएस" समरूपता मॉडल इस मॉडल को बहुत अच्छी तरह से स्वीकार करता है और यह एक सुंदर मानक मॉडल है। मुझे नहीं लगता कि यह एक बुरी बात है क्योंकि यह कोड को थोड़ा कम हैकी, अधिक टेस्टेबल और इमो पढ़ने में आसान बनाता है। लिखने के लिए थोड़ा और समय लगता है।

जबकि मैं स्वीकार करूंगा, यह आखिरी बार रहा है क्योंकि मैंने आखिरी बार यह सामान लिखा था, वहां अन्य पुस्तकालय हैं जो आपके लिए कतार में ख्याल रखते हैं।

Grizzly Nio Framework जबकि थोड़ा पुराना, पिछली बार मैंने इसका इस्तेमाल किया, मुख्य रनलोप खराब नहीं था। यह आपके लिए बहुत कतारबद्ध सेटअप करता है।

Apache Mina इसी तरह यह एक क्यूइंग फ्रेमवर्क प्रदान करता है।

लेकिन मेरा मतलब है कि अंत में यह इस बात पर निर्भर करता है कि आप किस पर काम कर रहे हैं।

  • क्या यह ढांचा के साथ खेलने के लिए सिर्फ एक व्यक्ति परियोजना है?
  • क्या यह उत्पादन कोड का एक टुकड़ा है जिसे आप वर्षों से जीना चाहते हैं?
  • क्या यह उत्पादन कोड का एक टुकड़ा है जिसे आप चालू कर रहे हैं?

जब तक आप इसे किसी सेवा के मूल भाग के रूप में उपयोग करने की योजना बना रहे हैं, तो आप ग्राहकों को प्रदान कर रहे हैं, मैं कहूंगा कि आपका दृष्टिकोण ठीक है। इसमें लंबे समय तक रखरखाव के मुद्दे हो सकते हैं।

+0

मेरे लिए बहुत अच्छा इनपुट, धन्यवाद। मुझे नहीं लगता कि रजिस्टर ट्रम्प सर्विसिंग है, क्योंकि वेकअप केवल प्रतीक्षा लूप को प्रभावित करता है, बाकी लूप नहीं। लॉकिंग के लिए, क्या इसके बजाय एक साधारण निजी ऑब्जेक्ट को लॉक करना बेहतर होगा? (रजिस्टर ऑब्जेक्ट लॉक करने के लिए पूरी तरह से एक ऑब्जेक्ट) मुझे उम्मीद नहीं है कि बड़ी मात्रा में चैनलों को एक ही समय में पंजीकृत किया जाए, इसलिए मुझे लगता है कि एक रजिस्टर कतार थोड़ी अधिक है। लेकिन मुझे विचार पसंद है और भविष्य में इसे लागू कर सकता है। – riha

+0

आरई: चयन और सर्विसिंग, हाँ, मेरा मतलब यही है। जैसे ही आप अभी पंजीकरण के साथ निपटने के लिए एक खाली चक्र खर्च करेंगे। भयानक नहीं है, लेकिन अतिरिक्त ताला की आवश्यकता है और तुरंत निपटाया है। क्यूइंग सिस्टम में आपके पास आमतौर पर नॉन अवरुद्ध कतार होती है जो इन ताले की आवश्यकता को बढ़ाती है। –

+0

आरई: ताले, हाँ मैं एक आंतरिक ताला बनाउंगा जो कि चयनकर्ता से व्यक्तिगत रूप से निपटने के लिए है। लेकिन हाँ ऐसा लगता है जैसे आप जाने के लिए अच्छे हैं। –

4

बस चयनकर्ता आदि का इलाज थ्रेड सुरक्षित नहीं है, उसी धागे पर सभी चयनित संबंधित क्रियाएं करें, जैसा कि डारॉन ने सुझाव दिया था।

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

2

रजिस्टर(), और, चुनिंदा लूप में, आपको 'तैयार' शून्य होने पर जारी रखने से पहले एक छोटी सी नींद, रजिस्टर() को चलाने का मौका देने के लिए एक छोटी सी नींद की आवश्यकता है। कोई अतिरिक्त सिंक्रनाइज़ेशन नहीं: यह पहले से ही काफी खराब है; इसे और भी बुरा मत बनाओ। मैं पंजीकृत करने, रद्द करने, ब्याज ऑप्स बदलने आदि के लिए इन चीजों के इन कतारों का प्रशंसक नहीं हूं: वे केवल उन चीजों को अनुक्रमित करते हैं जो वास्तव में समानांतर में किए जा सकते हैं।

+0

क्या आप पंजीकरण कर सकते हैं कि पंजीकरण कैसे करें चैनल वास्तव में समानांतर में किया जा सकता है? यदि पंजीकरण केवल उसी धागे पर किया जा सकता है जो भी चयन करता है, तो यह समानांतर कैसे हो सकता है? इसके अलावा, आप "छोटी नींद" पर क्या विचार करते हैं? 1ms? 10ms? 100ms? – riha

+1

@riha एह? मैंने यह नहीं कहा है कि चैनल पंजीकृत करना केवल चयन() थ्रेड में ही किया जा सकता है। यह उस विषय पर आपके प्रश्न के उत्तर में, यहां वर्णित तकनीक के माध्यम से, एक अलग थ्रेड पर किया जा सकता है। निश्चित रूप से यह स्पष्ट है? नींद दो, 100 मिमी पर्याप्त होना चाहिए। – EJP

+0

आह, मैंने पढ़ा है [यहां] (http://stackoverflow.com/a/2179612/589008), क्षमा करें। लेकिन क्या हम कई चैनलों को "एक ही समय में पंजीकृत करते समय चयनकर्ता द्वारा लागू ताले में नहीं चल रहे हैं?" यदि ऐसा है, तो कतार का उपयोग करने पर लाभ कहां है? – riha

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