2013-02-15 61 views
8

मैं SwingWorker का उपयोग करके कुछ विचारों को आजमा देना चाहता था क्योंकि मैंने इसे बहुत अधिक उपयोग नहीं किया है। इसके बजाए, मैं एक मुद्दे में भाग गया और मैं यह नहीं समझ सकता कि क्या गलत है।स्विंगवर्कर अप्रत्याशित रूप से क्यों रोकता है?

यहाँ एक छोटी SSCCE कि इस समस्या (मैं यहाँ SSCCEs की तरह लोगों को पता है) को दर्शाता है है:

import javax.swing.SwingUtilities; 
import javax.swing.SwingWorker; 

public class SwingWorkerTest 
{ 
    public static void main (String[] args) 
    { 
     SwingUtilities.invokeLater (new Runnable() 
     { 
      @Override 
      public void run() 
      { 
       new MySwingWorker (500).execute(); 
       new MySwingWorker (900).execute(); 
       new MySwingWorker (1200).execute(); 
      } 
     }); 
    } 
} 

class MySwingWorker extends SwingWorker<Void, Void> 
{ 
    private int ms; 

    public MySwingWorker (int ms) 
    { 
     this.ms = ms; 
    } 

    @Override 
    protected Void doInBackground() 
    { 
     Thread t = Thread.currentThread(); 

     for (int i = 0; i < 50; i++) 
     { 
      try 
      { 
       Thread.sleep (ms); 
      } 
      catch (InterruptedException e) 
      { 
       e.printStackTrace(); 
      } 

      System.out.println ("I am thread with " + ms + " sleep in iteration " + i + ": " + t.getName() + " (" + t.getId() + ")"); 
     } 

     return null; 
    } 
} 

तो मेरी कार्यक्रम 3 SwingWorkers कि स्क्रीन पर एक लाइन प्रिंट तो मिलीसेकेंड की निर्धारित संख्या के लिए सो बनाना चाहिए और फिर लाइन को दोबारा प्रिंट करें और फिर सोएं आदि। मैं SwingWorker एस स्विंग के थ्रेड के भीतर से बना देता हूं क्योंकि अन्यथा वे भी शुरू नहीं करेंगे।

तो उम्मीद उत्पादन होता है:

I am thread with 500 sleep in iteration 0: SwingWorker-pool-1-thread-1 (15) 
I am thread with 900 sleep in iteration 0: SwingWorker-pool-1-thread-2 (16) 
I am thread with 500 sleep in iteration 1: SwingWorker-pool-1-thread-1 (15) 
I am thread with 1200 sleep in iteration 0: SwingWorker-pool-1-thread-3 (17) 
I am thread with 500 sleep in iteration 2: SwingWorker-pool-1-thread-1 (15) 
I am thread with 900 sleep in iteration 1: SwingWorker-pool-1-thread-2 (16) 
I am thread with 500 sleep in iteration 3: SwingWorker-pool-1-thread-1 (15) 
I am thread with 1200 sleep in iteration 1: SwingWorker-pool-1-thread-3 (17) 
I am thread with 500 sleep in iteration 4: SwingWorker-pool-1-thread-1 (15) 
I am thread with 900 sleep in iteration 2: SwingWorker-pool-1-thread-2 (16) 
I am thread with 500 sleep in iteration 5: SwingWorker-pool-1-thread-1 (15) 
I am thread with 500 sleep in iteration 6: SwingWorker-pool-1-thread-1 (15) 
I am thread with 900 sleep in iteration 3: SwingWorker-pool-1-thread-2 (16) 
I am thread with 1200 sleep in iteration 2: SwingWorker-pool-1-thread-3 (17) 
I am thread with 500 sleep in iteration 7: SwingWorker-pool-1-thread-1 (15) 
............. 
150 लाइनों के लिए कुल

और इतने पर (3 कार्यकर्ताओं से प्रत्येक के लिए x 50 पुनरावृत्तियों)

इसके बजाय, उत्पादन मैं मिलता है:

I am thread with 500 sleep in iteration 0: SwingWorker-pool-1-thread-1 (15) 
I am thread with 900 sleep in iteration 0: SwingWorker-pool-1-thread-2 (16) 
I am thread with 500 sleep in iteration 1: SwingWorker-pool-1-thread-1 (15) 

और यही वह है। बस 3 लाइनें इसके बाद कार्यक्रम निकलता है। try catch ब्लॉक से कहीं भी कोई स्टैकट्रैक नहीं है।

1)। 1200 एमएम के साथ कार्यकर्ता कहाँ सोता है? असल में, अगर मैं 100000 के साथ 1200ms को प्रतिस्थापित करता हूं, तो यह कार्यकर्ता भी 1 पंक्ति प्रिंट करता है ... हाँ, केवल एक। अजीब ...

2)। श्रमिक क्यों रुकते हैं? (और मुझे सामान की 150 लाइनें नहीं मिलती हैं)

मैंने विंडोज 7 64-बिट पर जेआरई 7 अपडेट 11 का उपयोग करके इस कार्यक्रम को चलाया।

पीएस: मुझे पूरा यकीन है कि the bug mentioned here जेआरई के इस संस्करण में तय किया गया था, क्योंकि मुझे कंसोल पर मुद्रित थ्रेड आईडी के रूप में 2 अलग-अलग मान (15 और 16) मिलते हैं। यह पहली बात थी जिस पर मुझे संदेह था।

उत्तर

9

मेरा मानना ​​है कि स्विंग इवेंट थ्रेड को जीवित रखने के लिए आपको एक दृश्यमान स्विंग शीर्ष स्तर की विंडो दिखाने की आवश्यकता है। अन्यथा कार्यक्रम गैर-डेमन धागे की कमी के लिए बंद हो जाएगा।

संपादित करें:
साबित करने के लिए कि SwingWorker धागा एक Daemon धागा है, बस इसे परीक्षण करने के लिए कोड की एक पंक्ति जोड़ें:

System.out.println("I am thread with " + ms + " sleep in iteration " 
    + i + ": " + t.getName() + " (" + t.getId() + ")"); 

// **** added 
System.out.println("Daemon?: " + Thread.currentThread().isDaemon()); 
+0

+1 क्या स्विंगवर्कर का 'doInBackground' गैर-डिमन थ्रेड में निष्पादित करता है? –

+1

@ Eng.Fouad: कृपया संपादित करें देखें। संपादित करें: या जैसा आपने किया है स्रोत को देखें। आपके उत्तर में 1+! –

3

आप किसी भी यूआई बनाने की कोशिश की? या मुख्य धागे को बाहर निकलने से रोकने के लिए मुख्य के अंत में new Object().wait(); जैसे कुछ डालना?

मैं पूरी तरह से नहीं हूं कि यह मामला है, लेकिन बिना किसी वास्तविक UI दिखाए, मुझे पूरा यकीन है कि स्विंग कार्यकर्ता सिर्फ एक और धागा हैं, और आपने किसी को डिमन थ्रेड के रूप में कॉन्फ़िगर नहीं किया है, इसलिए मुख्य उन्हें शुरू करता है, मुख्य खत्म होता है, और प्रक्रिया निकलती है?

9

आप SwingWorker वर्ग स्रोत कोड की लाइन 771 (जावा SE 7) को देखें, तो:

thread.setDaemon(true); 

आपको लगता है कि SwingWorker एक डेमॉन धागा भीतर क्रियान्वित किया जाता है, और जावा में JVM अगर समाप्त हो जाएगा देखेंगे सभी गैर-डिमन धागे समाप्त हो गए हैं।

+4

पवित्र बकवास, आप लोग सही हैं। स्विंगवर्कर्स डेमॉन थ्रेड के रूप में चलाते हैं। यह मेरे दिमाग को पार भी नहीं किया। धन्यवाद, StackOverflow, आप हमेशा सब कुछ का जवाब है: डी। –

4

जैसा कि पहले से ही उल्लेख किया गया है, आप धागे को जीवित रखने के लिए यूआई का उपयोग कर सकते हैं।

वैकल्पिक रूप से, आप क्या कर सकते हैं SwingWorker#get (या जो कुछ भी थ्रेड समाप्त होने से रोकने के लिए मुख्य थ्रेड को रोकता है) का उपयोग करने के लिए उपयोग करता है। ऐसा करके, आप उम्मीद के अनुसार आउटपुट प्राप्त करेंगे। यहां संशोधित कोड है, जो आप चाहते हैं।

import javax.swing.SwingUtilities; 
import javax.swing.SwingWorker; 
import java.util.concurrent.ExecutionException; 

public class SwingWorkerTest 
{ 
    public static void main (String[] args) 
    { 
     final MySwingWorker w1 = new MySwingWorker (500), 
     w2 = new MySwingWorker (900), 
     w3 = new MySwingWorker (1200); 
     SwingUtilities.invokeLater (new Runnable() 
     { 
      @Override 
      public void run() 
      { 
       w1.execute(); 
       w2.execute(); 
       w3.execute(); 
      } 
     }); 

     try{ 
      // you can replace the code in this block 
      // by anything that keeps the program from 
      // terminating before the threads/SwingWorkers. 
      w1.get(); 
      w2.get(); 
      w3.get(); 
     }catch(InterruptedException e){ 
      System.err.println("InterruptedException occured"); 
     }catch(ExecutionException e){ 
      System.err.println("InterruptedException occured"); 
     } 

    } 
} 

class MySwingWorker extends SwingWorker<Void, Void> 
{ 
    private int ms; 

    public MySwingWorker (int ms) 
    { 
     this.ms = ms; 
    } 

    @Override 
    protected Void doInBackground() 
    { 
     Thread t = Thread.currentThread(); 

     for (int i = 0; i < 50; i++) 
     { 
      try 
      { 
       Thread.sleep (ms); 
      } 
      catch (InterruptedException e) 
      { 
       e.printStackTrace(); 
      } 

      System.out.println ("I am thread with " + ms + " sleep in iteration " + i + ": " + t.getName() + " (" + t.getId() + ")"); 
     } 

     return null; 
    } 
} 
+0

धन्यवाद, यह सहायक है। –

+0

वास्तव में बहुत उपयोगी है। 1+ –

+0

आप +1 के लायक हैं :) –