2013-01-09 12 views
8

में धागे के लिए टाइमआउट सेट करें, मैं थ्रेड पूल के भीतर निष्पादित थ्रेड के लिए टाइमआउट सेट करना चाहता हूं। फिलहाल मैं निम्नलिखित कोड है:जावा: थ्रेडपूल

ExecutorService executor = Executors.newFixedThreadPool(8); 
for(List<String> l: partition) {    
    Runnable worker = new WorkerThread(l); 
    executor.execute(worker); 
}  

executor.shutdown(); 
while (!executor.isTerminated()) { 

} 

कोड सिर्फ उप-सूचियों में वस्तुओं की एक बड़ी सूची विभाजन और एकल धागे के भीतर इन sublist की प्रक्रिया। लेकिन यह बात नहीं है।

मैं थ्रेड पूल में प्रत्येक सिंगल थ्रेड को टाइमआउट देना चाहता हूं। पूल में केवल एक धागे के लिए मुझे निम्नलिखित समाधान मिला:

Future<?> future = null; 

for (List<String> l : partition) { 
    Runnable worker = new WorkerThread(l); 
    future = executor.submit(worker); 
} 

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

लेकिन यह एक से अधिक धागे के लिए काम नहीं करेगा। हो सकता है कि मुझे प्रत्येक थ्रेड को List<Future> सूची में रखना होगा और इस सूची में पुनरावृत्त करना होगा और प्रत्येक future ऑब्जेक्ट के लिए टाइमआउट सेट करना होगा?

कोई सुझाव?

CountDownLatch उपयोग करने के बाद संपादित करें:

CountDownLatch doneSignal = new CountDownLatch(partition.size()); 
List<Future<?>> tasks = new ArrayList<Future<?>>(); 
ExecutorService executor = Executors.newFixedThreadPool(8); 
for (List<String> l : partition) { 
    Runnable worker = new WorkerThread(l); 
    tasks.add(executor.submit(doneSignal, worker)); 
} 

doneSignal.await(1, TimeUnit.SECONDS); 
if (doneSignal.getCount() > 0) { 
    for (Future<?> fut : tasks) { 
    if (!fut.isDone()) { 
     System.out.println("Task " + fut + " has not finshed!"); 
     //fut.cancel(true) Maybe we can interrupt a thread this way?! 
    } 
    } 
} 

अब तक अच्छा काम करता है।

तो अगला सवाल यह है कि समय समाप्त होने वाले थ्रेड को कैसे बाधित किया जाए? मैं fut.cancel(true) कोशिश करते हैं और निम्नलिखित कार्यकर्ता सूत्र में कुछ महत्वपूर्ण छोरों में निर्माण जोड़ें:

if(Thread.interrupted()) { 
    System.out.println("!!Thread -> " + Thread.currentThread().getName() + " INTERRUPTED!!"); 
     return; 
} 

तो कार्यकर्ता धागा टाइमआउट के बाद "मारा" है। क्या यह एक अच्छा समाधान है?

इसके अलावा: क्या Future इंटरफ़ेस पर थ्रेड का नाम प्राप्त करना संभव है? फिलहाल मुझे Thread.interrupted() निर्माण की स्थिति में नाम प्रिंट करना होगा।

मदद के लिए धन्यवाद!

सम्मान

+1

हाँ यह और अधिक काम करता है, बस सूची में फ़्यूचर्स रखें। – Fildor

+4

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

+1

@ डेविडस्वार्टज़ अच्छा बिंदु, हालांकि हालात हो सकते हैं कि काम एक दूसरे से पूरी तरह से स्वतंत्र हैं। मुझे नहीं पता कि ओपी वास्तव में इसके बारे में हालांकि, लेकिन ऐसा लगता है कि यह मामला यहां है। – fge

उत्तर

3

क्या आपने यह देखा है? ExecutorService.invokeAll

यह वही होना चाहिए जो आप चाहते हैं: श्रमिकों के एक बंडल को आमंत्रित करें और उन्हें बहुत लंबा समय लेने पर समय-समय पर रखें। टिप्पणी के बाद

संपादित करें - (नया विचार): आप कार्यों को पूर्ण करने और समय समाप्त करने के लिए के लिए await(long timeout, TimeUnit unit) के माध्यम से प्रतीक्षा करने के लिए एक CountDownLatch उपयोग कर सकते हैं! फिर आप भी एक shutdownNow करने और देखने जो कार्य बहुत लंबा ले लिया है सकते हैं ...

संपादित करें 2:

यह स्पष्ट करने के लिए:

  1. एक CountDownLatch जा प्रत्येक कार्यकर्ता द्वारा उलटी गिनती है , जब समाप्त हो जाए।
  2. मुख्य निष्पादन थ्रेड await में कहा गया लच पर टाइमआउट के साथ।
  3. जब वह कॉल रिटर्न देता है, तो आप लेटेस की गिनती को देख सकते हैं कि यह देखने के लिए कि क्या टाइमआउट हिट हुआ है (यदि यह है> 0)।
  4. ए) गिनती = 0, सभी कार्य समय पर समाप्त हो गए। बी) यदि नहीं, तो फ्यूचर्स लूप करें और उनके isDone देखें।आपको निष्पादक सेवा पर शटडाउन कॉल करने की आवश्यकता नहीं है।
  5. कॉल शट डाउन अगर आपको अब एक्जिक्यूटर की आवश्यकता नहीं है।

नोट: कार्यकर्ता समय के बीच में और अपने भविष्य के आइडोन() को कॉल कर सकते हैं।

+0

ठीक है ... फिर भी मुझे "execor.shutdown()" को कॉल करने के लिए "थ्रेड समाप्त होने पर प्रतीक्षा करना है, है ना? – sk2212

+0

जरूरी नहीं है। आप अभी भी भविष्य में वायदा के माध्यम से चक्र चला सकते हैं() या प्रत्येक भविष्य पर कॉल प्राप्त करें (या आप http://docs.oracle.com/javase/7/docs/api/java/util/concurrent का उपयोग कर सकते हैं /CountDownLatch.html मैं बाद वाले को "सबसे अच्छा" तरीका मानता हूं। – Fildor

+0

आह, ठीक है बहुत अच्छा। "CountDownLatch" बहुत अच्छा लग रहा है। आप कहते हैं (आपकी "संपादन" पंक्तियों में) कि मैं प्रतीक्षा करने के बाद अब शटडाउन चला सकता हूं। तो विधि शट डाउन अब सेट थ्रेड के कारण चल रहे सभी थ्रेड को रद्द कर देगा? यह मेरा अगला प्रश्न है क्योंकि मुझे invoke के साथ कोई रास्ता नहीं मिलता है यह पता लगाने के लिए कि कौन से थ्रेड टाइमआउट का उल्लंघन कर रहे हैं। शायद नए दृष्टिकोण के साथ यह संभव है? – sk2212

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

  • कोई संबंधित समस्या नहीं^_^