2012-07-06 28 views
10

निम्नलिखित कोड टुकड़ा पर विचार करें लिए प्रतीक्षा कर रहा:कई SwingWorkers

import java.awt.FlowLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.lang.reflect.InvocationTargetException; 
import javax.swing.*; 

public class TestApplet extends JApplet 
{ 
    @Override 
    public void init() 
    { 
     try 
     { 
      SwingUtilities.invokeAndWait(new Runnable() 
      { 
       @Override 
       public void run() 
       { 
        createGUI(); 
       } 
      }); 
     } 
     catch(InterruptedException | InvocationTargetException ex) 
     { 
     } 
    } 

    private void createGUI() 
    { 
     getContentPane().setLayout(new FlowLayout()); 
     JButton startButton = new JButton("Do work"); 
     startButton.addActionListener(new ActionListener() 
     { 
      @Override 
      public void actionPerformed(ActionEvent ae) 
      { 
       JLabel label = new JLabel(); 
       new Worker(label).execute(); 
      } 
     }); 
     getContentPane().add(startButton); 
    } 

    private class Worker extends SwingWorker<Void, Void> 
    { 
     JLabel label; 

     public Worker(JLabel label) 
     { 
      this.label = label; 
     } 

     @Override 
     protected Void doInBackground() throws Exception 
     { 
      // do work 
      return null; 
     } 

     @Override 
     protected void done() 
     { 
      getContentPane().remove(label); 
      getContentPane().revalidate(); 
     } 
    } 
} 

यहाँ एप्लेट कि कार्यकर्ता धागे के कुछ मध्यवर्ती परिणाम प्रदर्शित करता है में लेबल जोड़ने है (प्रकाशित करें/प्रक्रिया तरीकों का उपयोग कर)। अंत में, लेबल एप्लेट के फलक से हटा दिया जाता है। मेरा सवाल यह है कि, मैं अपने खुद के वर्कर थ्रेड के साथ कई लेबल कैसे बना सकता हूं, और जब वे सब कुछ कर रहे हैं तो उन्हें हटा दें?

अग्रिम धन्यवाद।

अद्यतन:

मुझे आशा है कि यह मेरा प्रश्न को स्पष्ट करेंगे। मैं लेबलों को एक बार में हटा देना चाहता हूं, जब सभी श्रमिकों ने अपना कार्य पूरा कर लिया है, प्रत्येक कार्यकर्ता के तुरंत बाद नहीं।

अद्यतन 2:

निम्नलिखित कोड कर रही करने के लिए मैं क्या जरूरत है लगता है। कृपया टिप्पणी करें कि मैंने इसे सही तरीके से किया है या नहीं। मुझे लगता है कि कुछ गड़बड़ है। एक समस्या यह है कि बटन के दाईं ओर वाले लेबल दिखाई देते हैं हालांकि उन्हें हटा दिया जाता है। सेट दृश्य (झूठा) इस मुद्दे को हल करने लगता है। क्या ऐसा करने का तरीका है?

import java.awt.FlowLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.lang.reflect.InvocationTargetException; 
import java.util.LinkedList; 
import java.util.List; 
import java.util.Queue; 
import java.util.Random; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 
import javax.swing.*; 

public class TestApplet extends JApplet 
{ 
    private Queue<JLabel> labels = new LinkedList<>(); 
    private static final Random rand = new Random(); 

    @Override 
    public void init() 
    { 
     try 
     { 
      SwingUtilities.invokeAndWait(new Runnable() 
      { 
       @Override 
       public void run() 
       { 
        createGUI(); 
       } 
      }); 
     } 
     catch(InterruptedException | InvocationTargetException ex){} 
    } 

    private void createGUI() 
    { 
     getContentPane().setLayout(new FlowLayout()); 
     JButton startButton = new JButton("Do work"); 
     startButton.addActionListener(new ActionListener() 
     { 
      @Override 
      public void actionPerformed(ActionEvent ae) 
      { 
       ExecutorService executor = Executors.newFixedThreadPool(10); 
       for(int i = 0; i < 10; i++) 
       { 
        JLabel label = new JLabel(); 
        getContentPane().add(label); 
        executor.execute(new Counter(label)); 
       } 
      } 
     }); 
     getContentPane().add(startButton); 
    } 

    private class Counter extends SwingWorker<Void, Integer> 
    { 
     private JLabel label; 

     public Counter(JLabel label) 
     { 
      this.label = label; 
     } 

     @Override 
     protected Void doInBackground() throws Exception 
     { 
      for(int i = 1; i <= 100; i++) 
      { 
       publish(i); 
       Thread.sleep(rand.nextInt(80)); 
      } 

      return null; 
     } 

     @Override 
     protected void process(List<Integer> values) 
     { 
      label.setText(values.get(values.size() - 1).toString()); 
     } 

     @Override 
     protected void done() 
     { 
      labels.add(label); 

      if(labels.size() == 10) 
      { 
       while(!labels.isEmpty()) 
        getContentPane().remove(labels.poll()); 

       getContentPane().revalidate(); 
      } 
     } 
    } 
} 
+0

तुम भी उन्हें एक सूची ('JList') में डालने पर विचार करें। –

+0

@AndrewTompson, हाँ, लेकिन मुझे कोड कहां रखना चाहिए जो उन्हें इंतजार करेगा? क्या यह एक और स्विंगवर्कर होना चाहिए जो कई अन्य लोगों को पैदा कर रहा है? – Vlad

+0

कृपया अपवाद निगलें मत। – trashgod

उत्तर

14

मैं सभी लेबलों को एक साथ हटाने का इरादा रखता हूं जब सभी श्रमिकों ने अपना कार्य पूरा कर लिया है।

के रूप में वर्णित here, एक CountDownLatch इस संदर्भ में अच्छी तरह से काम करता है। नीचे दिए गए उदाहरण में, प्रत्येक कार्यकर्ता पूरा होने पर latch.countDown() को आमंत्रित करता है, और latch.await() पर कार्यकर्ता ब्लॉक सभी कार्य पूरा होने तक। प्रदर्शन उद्देश्यों के लिए, Supervisor लेबल अपडेट करता है। टिप्पणी में दिखाया गया थोक हटाने, तकनीकी रूप से संभव है लेकिन आम तौर पर अप्रत्याशित है। इसके बजाय, JList या JTable पर विचार करें।

Worker Latch Test

import java.awt.Color; 
import java.awt.EventQueue; 
import java.awt.GridLayout; 
import java.awt.event.ActionEvent; 
import java.util.LinkedList; 
import java.util.List; 
import java.util.Queue; 
import java.util.Random; 
import java.util.concurrent.CountDownLatch; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 
import javax.swing.*; 

/** 
* @see https://stackoverflow.com/a/11372932/230513 
* @see https://stackoverflow.com/a/3588523/230513 
*/ 
public class WorkerLatchTest extends JApplet { 

    private static final int N = 8; 
    private static final Random rand = new Random(); 
    private Queue<JLabel> labels = new LinkedList<JLabel>(); 
    private JPanel panel = new JPanel(new GridLayout(0, 1)); 
    private JButton startButton = new JButton(new StartAction("Do work")); 

    public static void main(String[] args) { 
     EventQueue.invokeLater(new Runnable() { 

      @Override 
      public void run() { 
       JFrame frame = new JFrame(); 
       frame.setTitle("Test"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.add(new WorkerLatchTest().createGUI()); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    @Override 
    public void init() { 
     EventQueue.invokeLater(new Runnable() { 

      @Override 
      public void run() { 
       add(new WorkerLatchTest().createGUI()); 
      } 
     }); 
    } 

    private JPanel createGUI() { 
     for (int i = 0; i < N; i++) { 
      JLabel label = new JLabel("0", JLabel.CENTER); 
      label.setOpaque(true); 
      panel.add(label); 
      labels.add(label); 
     } 
     panel.add(startButton); 
     return panel; 
    } 

    private class StartAction extends AbstractAction { 

     private StartAction(String name) { 
      super(name); 
     } 

     @Override 
     public void actionPerformed(ActionEvent e) { 
       startButton.setEnabled(false); 
       CountDownLatch latch = new CountDownLatch(N); 
       ExecutorService executor = Executors.newFixedThreadPool(N); 
       for (JLabel label : labels) { 
        label.setBackground(Color.white); 
        executor.execute(new Counter(label, latch)); 
       } 
       new Supervisor(latch).execute(); 
     } 
    } 

    private class Supervisor extends SwingWorker<Void, Void> { 

     CountDownLatch latch; 

     public Supervisor(CountDownLatch latch) { 
      this.latch = latch; 
     } 

     @Override 
     protected Void doInBackground() throws Exception { 
      latch.await(); 
      return null; 
     } 

     @Override 
     protected void done() { 
      for (JLabel label : labels) { 
       label.setText("Fin!"); 
       label.setBackground(Color.lightGray); 
      } 
      startButton.setEnabled(true); 
      //panel.removeAll(); panel.revalidate(); panel.repaint(); 
     } 
    } 

    private static class Counter extends SwingWorker<Void, Integer> { 

     private JLabel label; 
     CountDownLatch latch; 

     public Counter(JLabel label, CountDownLatch latch) { 
      this.label = label; 
      this.latch = latch; 
     } 

     @Override 
     protected Void doInBackground() throws Exception { 
      int latency = rand.nextInt(42) + 10; 
      for (int i = 1; i <= 100; i++) { 
       publish(i); 
       Thread.sleep(latency); 
      } 
      return null; 
     } 

     @Override 
     protected void process(List<Integer> values) { 
      label.setText(values.get(values.size() - 1).toString()); 
     } 

     @Override 
     protected void done() { 
      label.setBackground(Color.green); 
      latch.countDown(); 
     } 
    } 
} 
+0

कार्यों को पूरा किया है, अच्छा उदाहरण – mKorbel

+0

आपको बहुत धन्यवाद! – Vlad

+1

आपका स्वागत है; इस तरह एक हाइब्रिड एप्लेट/एप्लिकेशन [टैग: जावा-वेब-स्टार्ट] का उपयोग करके विभिन्न प्रकार के परिनियोजन विकल्पों की पेशकश करता है, जैसा कि यहां दिखाया गया है [https://sites.google.com/site/drjohnbmatthews/subway)। – trashgod

1

आपके पास जो कोड है वह पहले से ही कुछ हद तक कर रहा है। जब बटन क्लिक किया जाता है तो आपको वास्तव में सामग्रीपटल में लेबल जोड़ना होगा। कुछ इस तरह:

JLabel label = new JLabel(); 
getContentPane().add(label); 
getContentPane().validate(); 
new Worker(label).execute(); 

यह लेबल में कुछ पाठ डाल करने के लिए, ताकि आप वास्तव में इसे देख जब यह स्क्रीन में जोड़ा जाता है एक अच्छा विचार हो सकता है।

JLabel label = new JLabel("Hello...I am here"); 

और अंत में विधि doInBackground() में आप कुछ कार्य के रूप में लेबल अद्यतन करने के लिए कुछ कोड जोड़ सकते हैं चल रहा है:

for(int i = 0;i < 100; i++){ 
      Thread.sleep(20); 
      label.setText("Counting..." + i); 
    } 

इस तरह से आप वास्तव में काम चल रहा है देखते हैं। यदि आप कई बार बटन क्लिक करते हैं तो आप कई लेबल देखते हैं और कार्य पूरा होने के बाद वे गायब हो जाते हैं।

+0

तेजी से उत्तर के लिए धन्यवाद। मैंने इसे चिपकाए जाने से पहले कोड को सरल बना दिया। लेबल में वास्तव में कुछ पाठ है और सामग्री फलक में जोड़ा गया है। :) हालांकि सुझावों के लिए धन्यवाद। मुझे लगता है कि मैंने अपना प्रश्न स्पष्ट रूप से नहीं बताया था। मेरा इरादा है कि सभी लेबल एक साथ हटा दें जब उनके सभी श्रमिकों ने – Vlad