2009-09-01 19 views
86

मेरे पास एक ऐसा फ़ंक्शन है जो पैटर्न के लिए स्ट्रिंग्स की सूची खोजने के लिए Pattern.compile और Matcher का उपयोग करता है। यह फ़ंक्शन एकाधिक धागे में उपयोग किया जाता है। जब थ्रेड बनाया जाता है तो प्रत्येक थ्रेड में Pattern.compile को पारित एक अद्वितीय पैटर्न होगा। धागे और पैटर्न की संख्या गतिशील हैं, जिसका अर्थ है कि मैं कॉन्फ़िगरेशन के दौरान अधिक पैटर्न और धागे जोड़ सकता हूं।जावा रेगेक्स थ्रेड सुरक्षित है?

क्या मुझे रीजिक्स का उपयोग करने पर इस फ़ंक्शन पर "सिंक्रनाइज़" करने की आवश्यकता है? जावा थ्रेड में regex सुरक्षित है?

TIA

उत्तर

108

हाँ, इस (पैटर्न) वर्ग के Pattern class

उदाहरण के लिए जावा API दस्तावेज़ों से अडिग हैं और कई समवर्ती धागे द्वारा उपयोग के लिए सुरक्षित हैं। इस तरह के उपयोग के लिए Matcher क्लास के उदाहरण सुरक्षित नहीं हैं।

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

+15

पैटर्न ऑब्जेक्ट्स थ्रेड सुरक्षित हैं, लेकिन 'संकलन()' विधि नहीं हो सकती है।पिछले कुछ वर्षों में दो या तीन बग हैं जो बहुसंख्यक वातावरण में संकलन विफल हो गए हैं। मैं एक सिंक्रनाइज़ ब्लॉक में संकलन करने की सिफारिश करेंगे। –

+2

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

+1

ध्यान दें कि "पैटर्न" का स्रोत ओरेकल जेडीके वितरण में है (http://www.oracle.com/technetwork/java/faq-141681.html#A14 के अनुसार: "जावा 2 एसडीके, मानक संस्करण में स्वयं शामिल है src.zip नामक एक फ़ाइल जिसमें जावा पैकेज में सार्वजनिक कक्षाओं के लिए स्रोत कोड शामिल है ") ताकि कोई भी अपने आप को तुरंत देख सकें। –

3

आपको लगता है कि धागा सुरक्षा के साथ-साथ आसपास के कोड को ध्यान में रखना है याद करने की आवश्यकता है, आप भाग्य में दिखाई देते हैं। तथ्य यह है कि Matchers पैटर्न की matcher फैक्टरी विधि का उपयोग करके बनाए गए हैं और सार्वजनिक रचनाकारों की कमी एक सकारात्मक संकेत है। इसी तरह, आप Pattern को बनाने के लिए compile स्थैतिक विधि का उपयोग करते हैं।

तो, संक्षेप में, आप उदाहरण की तरह कुछ करना है, तो:

Pattern p = Pattern.compile("a*b"); 
Matcher m = p.matcher("aaaaab"); 
boolean b = m.matches(); 

आप बहुत अच्छी तरह से करना चाहिए।

स्पष्टता के लिए कोड उदाहरण का पालन करें: ध्यान दें कि इस उदाहरण का दृढ़ता से तात्पर्य है कि इस प्रकार बनाई गई मैचर पैटर्न और परीक्षण के साथ थ्रेड-लोकल है। यानी, आपको इस प्रकार किसी भी अन्य थ्रेड के लिए बनाए गए Matcher का पर्दाफाश नहीं करना चाहिए।

स्पष्ट रूप से, यह किसी भी थ्रेड-सुरक्षा प्रश्न का जोखिम है। वास्तविकता यह है कि कोई भी कोड थ्रेड-असुरक्षित बनाया जा सकता है यदि आप पर्याप्त मेहनत करते हैं। सौभाग्य से, wonderfulbooks हैं जो हमें उन तरीकों का पूरा समूह सिखाते हैं जिन्हें हम अपने कोड को बर्बाद कर सकते हैं। अगर हम उन गलतियों से दूर रहते हैं, तो हम थ्रेडिंग समस्याओं की अपनी संभावना को बहुत कम करते हैं।

+0

इसे थ्रेड सुरक्षा के साथ क्या करना है? –

+0

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

+1

ठीक है, तो आप बस इतना कह रहे हैं कि उपयोग के बिंदु पर एक स्ट्रिंग से एक पैटर्न फिर से बनाना, समेकन मुद्दों से निपटने के जोखिम पर इसे कुशल बनाने के लिए बेहतर है? मैं आपको वह दूंगा। मैं कारखाने के तरीकों और सार्वजनिक रचनाकारों के बारे में उस वाक्य के साथ उलझन में था, जो इस विषय को लाल हेरिंग w/r/t जैसा लगता है। –

8

Thread-safety with regular expressions in Java

सारांश:

जावा नियमित अभिव्यक्ति एपीआई एक भी संकलित पैटर्न अनेक मिलान संचालन भर में साझा करने के लिए अनुमति देने के लिए बनाया गया है।

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

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

+2

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

2

Matcher.java के लिए कोड पर एक त्वरित रूप से मेल खाने वाले पाठ, समूह के लिए सरणी, बनाए रखने के लिए कुछ अनुक्रमणिका और कुछ boolean एस अन्य राज्यों के लिए सदस्य चर का एक गुच्छा दिखाता है। यह सभी एक राज्य Matcher पर इंगित करता है जो एकाधिक Threads द्वारा उपयोग किए जाने पर अच्छी तरह से व्यवहार नहीं करेगा। तो JavaDoc करता है:

इस वर्ग के उदाहरण कई समवर्ती धागे द्वारा उपयोग के लिए सुरक्षित नहीं है।

यह केवल एक मुद्दा है, तो, के रूप में @Bob क्रॉस बताते हैं, तो आप अपने रास्ते से हट जाने के अलग Thread रों में अपने Matcher के उपयोग की अनुमति है। यदि आपको ऐसा करने की आवश्यकता है, और आपको लगता है कि सिंक्रनाइज़ेशन आपके कोड के लिए एक मुद्दा होगा, तो आपके पास एक विकल्प है जो ThreadLocal स्टोरेज ऑब्जेक्ट का उपयोग करने के लिए Matcher प्रति कार्य थ्रेड बनाए रखने के लिए है।

1

सारांश में, आप पुन: उपयोग कर सकते हैं (स्थैतिक चर में रखने के लिए) संकलित पैटर्न (रों) और जब कुछ स्ट्रिंग

import java.util.regex.Matcher; 
import java.util.regex.Pattern; 

/** 
* Validation helpers 
*/ 
public final class Validators { 

private static final String EMAIL_PATTERN = "^[_A-Za-z0-9-]+(\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9-]+(\\.[A-Za-z0-9-]+)*(\\.[A-Za-z]{2,})$"; 

private static Pattern email_pattern; 

    static { 
    email_pattern = Pattern.compile(EMAIL_PATTERN); 
    } 

    /** 
    * Check if e-mail is valid 
    */ 
    public static boolean isValidEmail(String email) { 
    Matcher matcher = email_pattern.matcher(email); 
    return matcher.matches(); 
    } 

} 

http://zoomicon.wordpress.com/2012/06/01/validating-e-mails-using-regular-expressions-in-java/ देखने के खिलाफ उन regex pattens को मान्य करने के लिए आवश्यक उन्हें बताएं कि आप नए matchers देने के लिए (अंत के पास) ई-मेल को सत्यापित करने के लिए उपरोक्त उपयोग किए गए रेगेक्स पैटर्न के संबंध में (यदि यह फिट नहीं है तो इसे ई-मेल सत्यापन के लिए जरूरी नहीं है क्योंकि इसे यहां पोस्ट किया गया है)

+3

आपका उत्तर पोस्ट करने के लिए धन्यवाद! कृपया सावधानीपूर्वक [स्व-संवर्धन पर अक्सर पूछे जाने वाले प्रश्न] (http://stackoverflow.com/faq#promotion) को पढ़ना सुनिश्चित करें। किसी को यह जवाब और लिंक-टू-ब्लॉग पोस्ट देख सकता है और लगता है कि आपने ब्लॉग पोस्ट पोस्ट किया है ताकि आप इसे यहां से लिंक कर सकें। –

+1

'स्थिर {}' से परेशान क्यों? आप उस परिवर्तनीय प्रारंभिकरण को रेखांकित कर सकते हैं और 'पैटर्न' 'अंतिम' भी बना सकते हैं। – TWiStErRob

+1

मैं TWiStErRob का विरोध करता हूं: 'निजी स्थैतिक अंतिम पैटर्न ईमेल पैटर्न = Pattern.compile (EMAIL_PATTERN);' बेहतर है। –

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