2011-08-11 12 views
5

में लूप किए गए धागे को बाधित करना मैं समझने की कोशिश कर रहा हूं कि जावा में थ्रेड कैसे काम करते हैं और वर्तमान में जांच कर रहे हैं कि लूप किए गए थ्रेड को कैसे कार्यान्वित किया जा सकता है। कोड यह रहा:जावा

public static void main(String[] args) throws Exception { 
    Thread t = new Thread() { 
     @Override 
     public void run() { 
      System.out.println("THREAD: started"); 
      try { 
       while(!isInterrupted()) { 
        System.out.printf("THREAD: working...\n"); 
        Thread.sleep(100); 
       } 
      } catch(InterruptedException e) { 
       // we're interrupted on Thread.sleep(), ok 

       // EDIT 
       interrupt(); 

      } finally { 
       // we've either finished normally 
       // or got an InterruptedException on call to Thread.sleep() 
       // or finished because of isInterrupted() flag 

       // clean-up and we're done 
       System.out.println("THREAD: done"); 
      }    
     } 
    }; 

    t.start(); 
    Thread.sleep(500); 
    System.out.println("CALLER: asking to stop"); 
    t.interrupt(); 
    t.join(); 
    System.out.println("CALLER: thread finished"); 
} 

धागा मैं बनाने indended अभी या बाद में बाधित हो रहा है। इसलिए, जब मैं प्रतीक्षा प्रकार (sleep, join, wait) में मामलों को संभालने के लिए मुझे InterruptedException पर जाने की आवश्यकता है, तो मुझे यह तय करने के लिए अवरोधित() ध्वज है।

चीजें मैं स्पष्ट करना चाहते हैं कर रहे हैं:

  1. यह काम इस तरह का के लिए रुकावट तंत्र का उपयोग करने के लिए ठीक है? (volatile boolean shouldStop होने की तुलना में)
  2. क्या यह समाधान सही है?
  3. क्या यह सामान्य है कि मैं InterruptedException निगलता हूं? मुझे वास्तव में दिलचस्पी नहीं है कि कोड का टुकड़ा क्या था जहां किसी ने मेरे धागे को बाधित करने के लिए कहा था।
  4. क्या इस समस्या को हल करने के लिए कोई कम तरीका हैं? (मुख्य बिंदु रहा है 'अनंत' पाश)

संपादित जोड़ा गया InterruptedException के लिए पकड़ में interrupt() करने के लिए कॉल।

+2

यह ठीक है, लेकिन बेहतर नहीं है क्योंकि इसकी कार्यक्षमता को विस्तारित नहीं किया गया है। एक मानक थ्रेड द्वारा उपयोग किए जाने के लिए एक रननेबल लागू करें। –

उत्तर

4

मैं जवाब नहीं दे रहा हूं। 3:

असल में सवाल यह है कि: एक बाधित अपवाद का क्या उद्देश्य है? यह आपको अवरुद्ध करना बंद करने के लिए कहता है (उदा। सोना) और जल्दी वापस आना।

वहाँ दो एक InterruptedException से निपटने तरीके हैं:

  • Rethrow यह, बाधित तो धागा रहता
  • फिर Thread.currentThread.interrupt() स्थापित करने और अपने सफाई कार्य करते हैं। इस तरह से आप सुनिश्चित करें कि आपके सूत्र में एक और तरीका नींद शुरू फिर से

, बस निगलने एक InterruptedException एक अच्छा इस तरह के एक बाधा के प्रयोजन के अंत में समाप्त करने के लिए है जो के बारे में विचार नहीं है फेंक होगा हो सकता है। लेकिन आपको केवल बाधा देने के लिए कहा जाता है ताकि आपके पास अभी भी साफ करने का समय हो।

इस मामले में यह मेरे 'ओवररेक्शन' हो सकता है, लेकिन आम तौर पर ऐसा कोड बहुत जटिल है और आप कैसे जानते हैं कि इस थ्रेड में कुछ फॉलो-अप-कोड एक अवरोध विधि को फिर से कॉल नहीं करेगा?

संपादित

अन्यथा मुझे लगता है कि तुम क्या कर रहे हैं ठीक है। मेरे लिए थोड़ा आश्चर्यजनक, हालांकि, क्योंकि मैंने कभी भी अपने कोड में किसी को भी ऐसा नहीं देखा।

और दिलचस्प लेख का कारण बताते हुए यहां पाया जा सकता: http://www.ibm.com/developerworks/java/library/j-jtp05236/index.html

+0

ठीक है, मेरा मानना ​​है कि पुनर्स्थापन एक मामला नहीं है, क्योंकि मैं थ्रेड के 'रन()' से नहीं फेंक सकता हूं। क्या मुझे 'इंटरप्ट() 'कॉल करना चाहिए? – agibalov

+0

अवरुद्ध है बाधित फ्लैग को रीसेट नहीं करता है। और आप बिना किसी बाधा के लंबे समय तक प्रतीक्षा करने या सोने के लिए सोने के थ्रेड को कैसे रोकते हैं? –

+0

आप सही हैं। बाधित() रीसेट कर रहा है ... –

2
  1. हाँ, यह ठीक है। आपको दस्तावेज करना चाहिए कि थ्रेड/रननेबल को कैसे रोकना चाहिए।आप अपने रननेबल कार्यान्वयन पर एक समर्पित स्टॉप विधि जोड़ सकते हैं जो रोक तंत्र को समाहित करता है। या तो बाधा का उपयोग करें, या एक समर्पित बूलियन मूल्य, या दोनों का उपयोग करें।
  2. हाँ, को छोड़कर अच्छा अभ्यास जब InterruptedException पकड़ने बाधा स्थिति बहाल करने के लिए है: Thread.currentThread().interrupt();
  3. नहीं, आप बाधा स्थिति को वापस हासिल करना चाहिए
  4. कोई नहीं है कि मैं
1

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

2) हाँ

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

4) कोई

1

व्यवधान का उपयोग करना ठीक है, लेकिन उनका उपयोग अच्छी तरह से करें। आपको अपने पकड़ में Thread.currentThread().interrupt() फिर से फेंकना होगा।

public class MyThread extends Thread { 
    private static boolean correct = true; 

    @Override 
    public void run() { 
     while (true) { 
      // Do Something 1 
      for (int i = 0; i < 10; i++) { // combined loop 
       // Do Something 2 
       try { 
        Thread.sleep(100); 
       } catch (InterruptedException ex) { 
        if (correct) 
         Thread.currentThread().interrupt(); // reinterrupting 
        System.out.println("First Catch"); 
        break; // for 
       } 
      } 
      try { 
       // Do Something 3 
       System.out.print("before sleep, "); 
       Thread.sleep(1000); 
       System.out.print("After sleep, "); 
      } catch (InterruptedException ex) { 
       if (correct) 
        Thread.currentThread().interrupt(); 
       System.out.println("Second catch"); 
       break; // while 
      } 
     } 
     System.out.println("Thread closing"); 
    } 

    private static void test() throws InterruptedException { 
     Thread t = new MyThread(); 
     t.start(); 
     Thread.sleep(2500); 
     t.interrupt(); 
     t.join(); 
     System.out.println("End of Thread"); 
    } 

    public static void main(String[] args) 
      throws InterruptedException { 
     test(); 
     correct = false; // test "bad" way 
     test(); 
    } 
} 

एक और बात है, Interruptions हमेशा जब InputStreams पर इंतजार कर काम नहीं करते: यहाँ दिखा क्यों कोड का एक टुकड़ा है। फिर आप (कुछ के लिए) InterruptedIOException का उपयोग कर सकते हैं, लेकिन यह हमेशा काम नहीं करेगा। इन मामलों को समझने के लिए, आप कोड के इस टुकड़े को आजमा सकते हैं:

public class Mythread extends Thread { 
    private InputStream in; 

    public Mythread(InputStream in) { 
     this.in = in; 
    } 

    @Override 
    public void interrupt() { 
     super.interrupt(); 
     try { 
      in.close(); // Close stream if case interruption didn't work 
     } catch (IOException e) {} 
    } 

    @Override 
    public void run() { 
     try { 
      System.out.println("Before read"); 
      in.read(); 
      System.out.println("After read"); 
     } catch (InterruptedIOException e) { // Interruption correctly handled 
      Thread.currentThread().interrupt(); 
      System.out.println("Interrupted with InterruptedIOException"); 
     } catch (IOException e) { 
      if (!isInterrupted()) { // Exception not coming from Interruption 
       e.printStackTrace(); 
      } else { // Thread interrupted but InterruptedIOException wasn't handled for this stream 
       System.out.println("Interrupted"); 
      } 
     } 
    } 

    public static void test1() // Test with socket 
      throws IOException, InterruptedException { 
     ServerSocket ss = new ServerSocket(4444); 
     Socket socket = new Socket("localhost", 4444); 
     Thread t = new Mythread(socket.getInputStream()); 
     t.start(); 
     Thread.sleep(1000); 
     t.interrupt(); 
     t.join(); 
    } 

    public static void test2() // Test with PipedOutputStream 
      throws IOException, InterruptedException { 
     PipedInputStream in = new PipedInputStream(new PipedOutputStream()); 
     Thread t = new Mythread(in); 
     t.start(); 
     Thread.sleep(1000); 
     t.interrupt(); 
     t.join(); 
    } 

    public static void main(String[] args) throws IOException, InterruptedException { 
     test1(); 
     test2(); 
    } 
}