2014-11-14 6 views
7

के लिए प्रस्तुत मिलता है। कभी-कभी मुझे लगता है कि एक डेडलॉक का सामना करना पड़ रहा है लेकिन यह काम नहीं कर सकता है कि यह कहां या क्यों हो रहा है इसलिए मैं कार्य पर एक टाइमआउट सेट करना चाहता हूं, मुझे नहीं पता कि यह कैसे है?मैं कैसे <strong>ExecutionService</strong> के एक कार्यान्वयन के लिए <strong>प्रतिदेय</strong> कार्यों (<strong>प्रस्तुत का उपयोग कर()</strong>) प्रस्तुत एक प्रतिदेय कार्य एक ExecutorService टाइमआउट

मैं

  1. उपयोग invokeAny()के बजाय ExecutionService पर प्रस्तुत करना चाहिए() जब कार्य प्रस्तुत करने और एक समय समाप्ति निर्धारित किया है। मैं सबमिट() का उपयोग कर समय-समय पर कई कार्यों को सबमिट करता हूं, क्या मैं इस तरह invokeAny() का उपयोग भी कर सकता हूं, मैं सतर्क हूं क्योंकि मुझे समझ में नहीं आ रहा है कि सबमिट() विधि क्यों नहीं है जो टाइमआउट लेती है।
  2. संशोधित KeepAliveTime मेरी ExecutorService की मेरी निर्माता में (लेकिन मुझे लगता है कि यह कुछ और
  3. मेरे वास्तविक प्रतिदेय कार्यान्वयन को संशोधित कर रहा है, लेकिन अगर इसके गतिरोध है यह नहीं कर सकते खुद undeadlock।

विकल्प 1 लगता है केवल व्यवहार्य समाधान है, लेकिन यह है?

अधिक जानकारी

मैंने सोचा था कि इसके लायक expla हो सकता है अगर यह समाधान के साथ मदद करता है तो यह प्रक्रिया अधिक विस्तार से कैसे कार्य करती है।

कॉल करने योग्य कार्य पी 1 शुरू हो गया है और एक फ़ोल्डर पर काम करता है, और इसमें सभी फाइलें और फ़ोल्डर्स काम करते हैं और गानों को समूहों में समूहित करना शुरू करते हैं, यह एक्जिक्यूटर्स सर्विस ईएस 1 के अंदर चलता है, और केवल पी 1 का एक ही उदाहरण ES1 को सबमिट किया जाता है।

हमारे पास तीन अन्य कॉल करने योग्य वर्ग भी हैं: पी 2, पी 3, और पी 4 - इनमें से प्रत्येक की अपनी संबंधित एक्जिक्यूटर सेवा, ईएस 2, ईएस 3, ईएस 4 है)। एक बार पी 1 ने एक समूह बनाया है, तो यह डेटा के रूप में पारित समूह के साथ संबंधित ईएस को एक कार्य प्रस्तुत करता है, यानी यह पी 2 से ई 2, पी 3 या पी 3 या पी 4 को ई 4 में प्रस्तुत कर सकता है, जिसे वह चुनता है, के विवरण पर निर्भर करता है ग्रुपिंग, पी 2, पी 3 और पी 4 सभी अलग-अलग चीजें करते हैं।

मान लें कि उसने पी 2 का एक उदाहरण प्रस्तुत किया है, पी 2 पी 3 को ई 3 या पी 4 से ई 4 सबमिट करके प्रसंस्करण खत्म कर देगा। इसकी एकमात्र पाइपलाइन पी 3 केवल पी 4 में जमा हो सकती है, और एक बार सभी कार्यों को पी 4 और पी 4 में जमा कर दिया गया है, प्रसंस्करण के सभी कार्यों को समाप्त कर दिया गया है।

हम ES1, ES2, ES3 और ES4 निर्माण P1 के लिए कार्य प्रस्तुत करने के लिए, तो बदले में प्रत्येक ExecutorService पर बंद() कॉल तो, बंद() वापस नहीं होगा, जब तक P1 सभी समूहों प्रस्तुत करने समाप्त हो गया है, यह तब तक पूरा प्रसंस्करण ES2 पर शट डाउन() कॉल करता है जो तब तक वापस नहीं आ जाएगा जब तक ES2 ने इसे P2 कार्यों ecetera की कतार को मंजूरी दे दी हो।

बहुत बार सबकुछ बस मुझे रोकता है मानते हैं कि कुछ प्रक्रिया जारी रखने से अन्य प्रक्रियाओं को रोक रही है, इसलिए इस बिंदु पर मैं उन प्रक्रियाओं को रद्द करने का एक तरीका चाहता हूं जो बहुत अधिक समय लेते हैं ताकि अन्य जारी रह सकें, यह काफी कम बुरा है, फिर यह अनिश्चितता से लटका रहा है

उत्तर

पर अद्यतन मैं invokeAny का उपयोग कर() के रूप में सुझाव की कोशिश की, यह एक तरह से काम करता है। P1 P2 का एक उदाहरण E2 के लिए यह तो पूरा करने से पहले इंतजार कर रहा है प्रस्तुत करते हैं, तो उस तरह की ठीक है, क्योंकि जब प्रस्तुत() यह सिर्फ वहाँ किसी भी तरह से वापस आती है यह नहीं है आगे की प्रक्रिया लेकिन वहाँ दो मुद्दे हैं का उपयोग कर:

  1. प्रत्येक निष्पादक सेवा 500 की एक सीमाबद्ध कतार का उपयोग करती है, यह विचार यह है कि यदि पी 2 पी 1 की तुलना में बहुत धीमी है तो हम ईएस 2 पर चीजों को ढेर नहीं करते हैं और अंत में स्मृति से बाहर निकलते हैं। तो अब पी 1 तब तक खत्म नहीं होता जब तक कि वे कॉल को समाप्त नहीं कर लेते हैं, कतार प्रभावी रूप से छोटे होते हैं क्योंकि उनमें केवल ईएस 2 पर स्लॉट के लिए इंतजार करने वाले कार्यों को शामिल नहीं किया जाता है, लेकिन उनमें ऐसे कार्य होते हैं जो पहले ही ईएस 2 को सबमिट कर चुके हैं लेकिन इसके लिए प्रतीक्षा कर रहे हैं समाप्त।

  2. पाइपलाइन जंजीर है इसलिए यदि हम पी 1 से सबमिट किए गए कार्यों पर पीओ और पी 2 और पी 4 से सबमिट किए गए कार्यों पर किसी भी कार्य को पी 1 से पी 2 तक सबमिट किया जाता है तो यह तब तक वापस नहीं आएगा जब तक कि बाद में प्रोसेसिंग ई 4 से पूर्ण न हो जाए!

+0

(रोक अगर सभी कार्य एक निश्चित समय में पूरा नहीं करते हैं) आप सभी कार्यों पर एक समय समाप्ति सेट करना चाहते हैं या अलग से प्रत्येक कार्य के लिए एक समाप्ति सेट? –

+0

मुझे कोई भी काम चाहिए जो किसी और चीज को प्रभावित किए बिना रोकने के लिए बहुत लंबा समय लेता है, यानी मैं नहीं चाहता कि पूरी प्रक्रिया केवल उन कॉलबल्स को रोक दें जो बहुत अधिक समय लेते हैं (क्योंकि डेडलॉकिंग के कारण वे पूरे आवेदन को पूरी तरह से रोक रहे हैं) –

+0

आपको जावा के मामले में विशेष रूप से मृत लॉक देखना चाहिए। संसाधन विवाद कहां हो रहा है? क्या यह एक वास्तविक धागा मृत ताला है? आपका ऐप बस फांसी का मतलब मृत लॉक नहीं है। –

उत्तर

0

@ फिलिप व्हाइटहाउस द्वारा टिप्पणी एक बार मैंने कुछ संशोधन किए जाने के बाद काम किया।

संक्षेप में एक कस्टम थ्रेडपूल बनाएं जो शेड्यूल किए गए एक्सप्लोररपूल को enscapulates ताकि कार्य सबमिट किए जाने पर एक टाइमआउट सेट किया जा सके।

पूर्ण यहाँ समाधान:

How can I make shutdown work properly with this custom ExecutorService?

2

मुझे लगता है कि डेडलॉक खोजने और ठीक करने का सबसे अच्छा तरीका है। आप सिर्फ धागे को मार नहीं सकते हैं। आपको कार्य में किसी प्रकार का कार्य रद्दीकरण लागू करना चाहिए और यह कार्य रद्द करने के लिए इस कार्य को एएसके करना चाहिए। लेकिन अगर यह deadlocked है तो आप कुछ भी नहीं कर सकते हैं। You can use jsconsole to detect a deadlock

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

+0

शायद यह डेडलॉकिंग नहीं है, ऐसा लगता है लेकिन मैं किसी भी लंबे समय तक चलने वाले काम को समय-समय पर करना चाहता हूं चाहे वह डेडलॉकिंग हो या नहीं, इस सवाल का मुख्य जोर यह है कि क्या विकल्प 1 काम करेगा जैसा कि मुझे चाहिए या नहीं? –

+0

ने मेरा उत्तर – pomkine

+0

ओह अपडेट किया है, बाधा भाग ठीक है, समस्या यह है कि मुझे एहसास नहीं हुआ कि किसी भी ब्लॉक - निष्पादक सेवा को सबमिट करने का बिंदु यह है कि कॉलिंग कार्य जारी रख सकता है, यह कहकर कि कॉलिंग कार्य आमतौर पर जमा करने के बाद समाप्त होता है तो शायद यह काम करेगा। –

4

आप अमरूद के MoreExecutorsListeningExecutorService का उपयोग कर सकते हैं। यह आपकी समस्याओं को जादुई रूप से हल नहीं करेगा लेकिन कुछ सहायता प्रदान कर सकता है:

1) आप invokeAll के माध्यम से प्रत्येक Callable के लिए एक टाइमआउट सेट कर सकते हैं। यदि किसी कॉल करने योग्य समय के साथ समाप्त नहीं होता है, तो इसे मारा जाना चाहिए।

2) आप सभी ListenableFuture एस का वैश्विक मानचित्र बना सकते हैं, जहां उनमें से प्रत्येक सृजन पर एक ध्वज पंजीकृत करेगा और पूरा होने पर ध्वज साफ़ करेगा। इस तरह आप जानते होंगे कि इनमें से कौन से वायदा समस्या को कम करने में मदद नहीं कर पाए।

+0

धन्यवाद आशाजनक लग रहा है - मैं आगे की जांच करूंगा। –

0

सुनिश्चित नहीं हैं कि यह आप में मदद मिलेगी, लेकिन मैं जल्दी और आसानी से यह नुस्खा के साथ पहले गतिरोध खोज करने में कामयाब है, तो: ग्रहण में

  • डीबग
  • प्रजनन करते हैं "लटका"
  • सर्वर उदाहरण का चयन करें और ग्रहण डीबगर में "रोकें" बटन पर क्लिक करें। यह सभी धागे को रोक देगा।
  • अब थ्रेड सूची को नीचे स्क्रॉल करें। Deadlocked धागे लाल चिह्नित हैं। प्रत्येक थ्रेड उस ताले को दिखाता है जो ताले रखता है और ताले के लिए इंतजार कर रहा है।
  • लाभ!
+0

'लटका' पुन: उत्पन्न करें, यह कठिनाई है! –

0

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

एकल कॉल करने योग्य उदाहरण के लिए समाधान के बाद चेकआउट। वही आप भविष्य की कॉल सूची का उपयोग कर कॉलबेल की संख्या के लिए कार्यान्वित कर सकते हैं। यह future.get (...) विधि का उपयोग कर रहा है, जहां हमने टाइमआउट सेट किया है। यदि कॉल करने योग्य सेट टाइमआउट द्वारा निष्पादन समाप्त नहीं करता है, तो थ्रेड इसके निष्पादन को समाप्त कर देगा।

import java.util.concurrent.Callable; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 
import java.util.concurrent.Future; 
import java.util.concurrent.TimeUnit; 
import java.util.concurrent.TimeoutException; 

public class ThreadTimeOut{ 
    public static void main(String[] args) throws Exception { 
    ExecutorService executor = Executors.newSingleThreadExecutor(); 
    Future<String> future = executor.submit(new Task()); 

    try { 
     System.out.println("Started.."); 
     System.out.println(future.get(3, TimeUnit.SECONDS)); 
     System.out.println("Finished!"); 
    } catch (TimeoutException e) { 
     System.out.println("Terminated!"); 
    } 

    executor.shutdownNow(); 
    } 
} 

class Task implements Callable<String> { 
    @Override 
    public String call() throws Exception { 
     Thread.sleep(4000); // Just to demo a long running task of 4 seconds. 
     return "Ready!"; 
    } 
} 
संबंधित मुद्दे

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