2009-12-24 11 views
6

मान लीजिए कि मेरे पास एक धागा है जो किसी अन्य थ्रेड द्वारा उत्पादित वस्तुओं का उपभोग करता है। अपनी दौड़ विधि inQueue एक BlockingQueueकिस स्थिति के तहत BlockingQueue.take अवरोध अपवाद फेंक देगा?

boolean shutdown = false; 
while (!shutdown) { 
    try { 
     WorkItem w = inQueue.take(); 
     w.consume(); 
    } catch (InterruptedException e) { 
     shutdown = true; 
    } 
} 

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

+1

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

उत्तर

4

अवरुद्ध कतार की समाप्ति को सिग्नल करने का एक अच्छा तरीका कतार में 'जहर' मान जमा करना है जो शट डाउन हुआ है इंगित करता है। यह सुनिश्चित करता है कि कतार के अपेक्षित व्यवहार को सम्मानित किया जाता है। यदि आप कतार को साफ़ करने की परवाह करते हैं तो Thread.interupt() को कॉल करना शायद एक अच्छा विचार नहीं है।

कुछ कोड प्रदान करने के लिए:

boolean shutdown = false; 
while (!shutdown) { 
    try { 
     WorkItem w = inQueue.take(); 
     if (w == QUEUE_IS_DEAD) 
      shutdown = true; 
     else 
      w.consume(); 
    } catch (InterruptedException e) { 
     // possibly submit QUEUE_IS_DEAD to the queue 
    } 
} 
+0

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

3

javadoc के अनुसार, take() विधि InterruptedException फेंक देते हैं, तो इंतजार कर रहे हैं, जबकि बाधित।

+0

इसका क्या अर्थ है? "" प्रतीक्षा करते समय बाधित अगर संपादित करें: कभी नहीं। मैं नीचे FkYkko के जवाब से समझा। – WarLord

-1

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

+3

इसे एक परीक्षण में आज़माएं और "बेहद आश्चर्यचकित" हो ;-) – FkYkko

+0

"स्मार्ट लोग इसे बनाते हैं" प्लस "इंटरप्ट() थ्रेड को बाधित करता है" इसमें शामिल नहीं है "अवरुद्ध कतारें खाली होने तक इंटरप्ट स्थिति की जांच नहीं करती हैं"। उदाहरण के लिए, कम से कम एक कार्यान्वयन (सीएफ। Http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/concurrent/ArrayBlockingQueue.java#ArrayBlockingQueue। ले लो) ArrayBlockingQueue कॉल ReentrantLock.lockInterruptibly(), जो थ्रेड की इंटरप्ट स्थिति (अगली तत्व प्राप्त करने का प्रयास करने से पहले इंटरप्टेड एक्सेप्शन को बाधित करता है) को जांचता है। – user359996

2

मैंने उसी चीज के बारे में सोचा और take() के लिए जावाडोक पढ़ रहा था, मुझे विश्वास था कि कतार में सभी वस्तुओं को लेने के बाद ही यह बाधित अपवाद फेंक देगा, क्योंकि कतार में सामान था, तो उसे "इंतजार नहीं करना पड़ेगा "।

package se.fkykko.slask; 
import java.util.concurrent.ArrayBlockingQueue; 
import java.util.concurrent.BlockingQueue; 
import java.util.concurrent.atomic.AtomicLong; 

public class BlockingQueueTakeTest { 

public static void main(String[] args) throws Exception { 
    Runner t = new Runner(); 
    Thread t1 = new Thread(t); 
    for (int i = 0; i < 50; i++) { 
     t.queue.add(i); 
    } 
    System.out.println(("Number of items in queue: " + t.queue.size())); 
    t1.start(); 
    Thread.sleep(1000); 
    t1.interrupt(); 
    t1.join(); 
    System.out.println(("Number of items in queue: " + t.queue.size())); 
    System.out.println(("Joined t1. Finished")); 

} 

private static final class Runner implements Runnable { 
    BlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>(100); 
    AtomicLong m_count = new AtomicLong(0); 

    @Override 
    public void run() { 
     try { 
      while (true) { 
       queue.take(); 
       System.out.println("Took item " + m_count.incrementAndGet()); 
       final long start = System.currentTimeMillis(); 
       while ((System.currentTimeMillis() - start) < 100) { 
        Thread.yield(); //Spin wait 
       } 
      } 
     } 
     catch (InterruptedException ex) { 
      System.out.println("Interrupted. Count: " + m_count.get()); 
     } 
    } 
} 

} 

धावक 10-11 आइटम लेने के लिए और उसके बाद) अर्थात लेने खत्म (InterruptedException फेंक जाएगा, भले ही वहाँ अभी भी कतार में आइटम है जाएगा: लेकिन मैं एक छोटे से परीक्षण किए गए।

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

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