5

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

Stream.of(columns).parallel().forEach(column -> 
    result[column.index] = parseColumn(valueCache[column.index], column.type)); 

कॉलम ColumnDescriptor तत्व है जो बस दो गुणधर्म हैं स्तंभ अनुक्रमणिका पार्स किया जा सकता और प्रकार है जो कि यह कैसे पार्स करने के लिए परिभाषित करता है शामिल हैं। और कुछ नहीं। नतीजा एक ऑब्जेक्ट सरणी है जो परिणामी सरणी लेता है।

समस्या अब यह है कि पार्स फ़ंक्शन एक पारसी अपवाद फेंकता है, कि मैं कॉल स्टैक को आगे बढ़ाता हूं। चूंकि हम यहां समानांतर हैं, इसलिए इसे फेंक नहीं दिया जा सकता है। इसे संभालने का सबसे अच्छा तरीका क्या है?

मेरे पास यह समाधान है, लेकिन मैं इसे पढ़ने के लिए क्रिंग कर रहा हूं। ऐसा करने का एक बेहतर तरीका क्या होगा?

final CompletableFuture<ParseException> thrownException = new CompletableFuture<>(); 
Stream.of(columns).parallel().forEach(column -> { 
    try { 
     result[column.index] = parseColumn(valueCache[column.index], column.type); 
    } catch (ParseException e) { 
     thrownException.complete(e); 
    }}); 

if(thrownException.isDone()) 
    //only can be done if there is a value set. 
    throw thrownException.getNow(null); 

नोट्स: मुझे सभी अपवादों की आवश्यकता नहीं है। अगर मैं उन्हें अनुक्रमिक रूप से पार्स करता हूं तो मैं भी वैसे भी एक प्राप्त करूंगा। तो यह ठीक है।

+0

मेरे लिए यह पठनीय अन्य संभावना है जिसे मैं दबाए गए अपवादों के बारे में सोच सकता हूं ताकि आप कॉलम नंबर भी स्टोर कर सकें लेकिन स्टैक ट्रेस विशाल हो जाएगा, addsuppressed विधि सिंक्रनाइज़ भी हो सकती है या बस उपयोगकर्ता के अनुकूल संदेश का निर्माण कर सकती है – HRgiger

+1

मुझे लगता है कि यह अधिक है प्रयोग, क्योंकि यह असंभव है कि पार्सिंग सीएसवी फ़ाइल से बनाम बनाम एक महत्वपूर्ण मात्रा ले रही है (यानी, यह समयपूर्व अनुकूलन है)। यदि आपने फ़ाइल को पढ़ने के दौरान पार्स किया है, तो आपको शायद यह पता चल जाएगा कि रीडिंग खत्म होने पर सब कुछ पार्स किया गया है। – john16384

+0

डेटा पढ़ने एक बार ऑपरेशन है।लेकिन पार्सिंग विल को अलग-अलग सेटिंग्स के साथ बार-बार किया जाना चाहिए। यही कारण है कि मैं उस हिस्से को अनुकूलित करना चाहता हूं। – findusl

उत्तर

1

मुझे लगता है कि सवाल अधिक है, आप इसे सामान्य रूप से पार्स करते समय सामान्य रूप से क्या करते हैं?

क्या आप पहले अपवाद पर रुकते हैं, और पूरी प्रक्रिया को रोकते हैं? उस स्थिति में, अपवाद को रन टाइम अपवाद में लपेटें, और स्ट्रीम को निरस्त कर दें और इसे फेंक दें। रैपर अपवाद पकड़ो, इसे खोलें और इससे निपटें।

क्या आप खराब रिकॉर्ड छोड़ते हैं? फिर या तो 1. किसी सूची में त्रुटियों का ट्रैक रखें या 2. एक रैपर ऑब्जेक्ट बनाएं जो या तो एक पार्स किए गए परिणाम या त्रुटि को पकड़ सके (अपवादों को ट्रैक न करें, केवल त्रुटि का वर्णन करने के लिए आवश्यक न्यूनतम)।

बाद में जांच करें कि पहले विकल्प के लिए सूची में त्रुटियां हैं या रिकॉर्ड को प्रदर्शित करें जिसमें दूसरे विकल्प के लिए अलग-अलग त्रुटियां थीं।

+0

रनटाइम अपवाद काम करता है। मुझे यह मेरे समाधान से ज्यादा पसंद है। अभी भी इसे बहुत पसंद नहीं है, क्योंकि मैंने इस तरह के समानांतर धागे के माध्यम से एक रनटाइम अपवाद फेंक दिया है। प्रोग्रामिंग समानांतर होने से बचने के लिए मैंने कुछ सीखा। लेकिन चूंकि धारा मेरे लिए इसे संभालती है, मुझे लगता है कि अगर मुझे इन दिनों बेहतर जवाब नहीं मिलता है तो मैं जल्द ही आपका सही निशान लगाऊंगा :) – findusl

3

समस्या आपका गलत आधार है "चूंकि हम यहां समानांतर हैं, इसलिए इसे फेंक नहीं दिया जा सकता है।" समानांतर प्रसंस्करण में फेंकने के अपवादों को अस्वीकार करने का कोई विनिर्देश नहीं है। आप उस अपवाद को समानांतर धारा में उसी तरह फेंक सकते हैं जैसा कि आप अनुक्रमिक स्ट्रीम में करते हैं, इसे अनचेक अपवाद में लपेटकर, यदि यह एक चेक अपवाद है।

यदि थ्रेड में कम से कम एक अपवाद फेंक दिया गया है, तो forEach आमंत्रण कॉलर को (या उनमें से एक) को प्रसारित करेगा।

एकमात्र समस्या जो आप सामना कर सकते हैं, यह है कि मौजूदा कार्यान्वयन किसी अपवाद का सामना करते समय सभी धागे को पूरा करने की प्रतीक्षा नहीं करता है। यह

try { 
    Arrays.stream(columns).parallel() 
     .forEach(column -> 
      result[column.index] = parseColumn(valueCache[column.index], column.type)); 
} catch(Throwable t) { 
    ForkJoinPool.commonPool().awaitQuiescence(1, TimeUnit.MINUTES); 
    throw t; 
} 

का उपयोग कर के आसपास काम किया जा सकता है लेकिन आम तौर पर, आप इसकी आवश्यकता नहीं है के रूप में आप असाधारण मामले में समवर्ती संसाधित परिणाम पर नहीं पहुंच सकेगी।

+0

उस उत्तर के लिए समय लेने के लिए पहला धन्यवाद। यह जॉन 16384 उत्तर में एक ही बिंदु की ओर ले जाएगा। मैं एक बहु थ्रेड पर्यावरण में अपवाद फेंकना पसंद नहीं करता। कई थ्रेडों पर अपवाद बबबेलिंग कुछ ऐसा है जो मैंने थ्रेड के साथ काम करना सीखा जब मैंने बिना किसी जाने के बारे में सीखा। तो यह काम करता है, मैं काफी संतुष्ट नहीं हूँ। – findusl

+1

@findusl: यह दिलचस्प होगा, जिसने आपको बताया है कि किस तरह के तर्क के साथ, अपने पूरे जीवनकाल से बचने के लिए, सिर्फ इसलिए कि किसी ने कुछ दिन इसके बारे में कुछ बुरा कहा, काफी डरावना लगता है। और इससे बचने का आपका प्रयास कुछ भी नहीं बदलता है, न तो अर्थात् न ही तकनीकी रूप से। 'parseColumn' अभी भी एक बहु थ्रेडेड निष्पादन में अपवाद फेंक रहा है और कोई इसे पकड़ लेगा और इसे थ्रेड शुरू करने वाली नौकरी पर सौंप देगा। स्ट्रीम फ्रेमवर्क को करने की बजाय, इसे मैन्युअल रूप से करते समय बेहतर क्यों होना चाहिए? – Holger