Execute only one instance of SwingWorker

ε祈祈猫儿з 提交于 2019-12-25 07:43:27

问题


Suppose I have a Java GUI which shows in a panel 40 Batch objects from a selected zone which can go from A to Z.

The 40 Batch objects are queried from database which caches them by zone so that each request for a zone doesn't involve the database every time.

public class BatchView
{

  private int drawIt(Graphics g, String zone)
  {
     for(int i = 0; i<40; i++)
       {
          Batch tmpBatch = BatchDAO.getBatch(zone, i);
          //draw the tmpBatch object
       }
  }
}

public class BatchDAO 
{
  public static MyCache cache = new MyCache(5000);

  public getAllBatches(String zone)
  {
    ArrayList<Batch> batchArrayList = cache.get("batch-" + zone);
    if(batchArrayList == null)
    {
        BuildBatchSwingWorker buildBatchSwingWorker = new BuildBatchSwingWorker(zone);
        buildBatchSwingWorker.execute();
    }
    return batchList;
  }

  public Batch getBatch(String zone, int id)
  {
     //here I don't query database but exploit the cache
     ArrayList<Batch> batchArrayList = getAllBatches(String zone);
     for(int i = 0; i< batchArrayList.size(); i++)
     {
       if(batchArrayList.get(i).getId() == i)
            return batchArrayList.get(i);
     }
     //if batch is not found it means it hasn't loaded yet so I return null
     return null;
  }
}

Suppose the cache is correcly updated with a series of notifications and each time the drawIt() method correctly updates, how can I make it so that BuildBatchSwingWorker is not called multiple times concurrently for the same zone?


回答1:


Given your code I think that what really concerns you is not how many times SwingWorker executes but do database call just once and then use BatchDAO's cache.

You need to separate responsibilities properly, cache maintenace is a job for BatchDAO class and thus swing worker has nothing to do with it:

public class BatchDAO {
    ...
    public getAllBatches(String zone) {
        ArrayList<Batch> batchArrayList = cache.get("batch-" + zone);
        if(batchArrayList == null) {
            // here goes database call not swing worker!
        }
        return batchList;
    }
    ...
}

Then execute a swing worker in your GUI class (where it belongs):

public class BatchView {

    private int drawIt(Graphics g, String zone) {
        SwingWorker<Void, Batch> worker = new SwingWorker<Void, Batch>() {
            @Override
            protected Void doInBackground() throws Exception {
                for(int i = 0; i<40; i++) {
                    Batch tmpBatch = BatchDAO.getBatch(zone, i);
                    publish(tmpBatch);
                 }
                 return null;
             }

             @Override
             protected void process(List<Batch> batches) {
                 for(Batch batch : batches) {
                     //draw the batch object
                 }
             }
         };

         worker.execute();
    }

}

Note if cache.get("batch-" + zone) == null then database call would be performed only once, but if not then you will be using your chache and doInBackground() method would be executed in a blink of an eye, which I think is your goal.


Off-topic

Since I see a Graphics object as parameter in your BatchView class' constructor, I'd suggest you take a close read to Performing Custom Painting tutorial to avoid custom painting undesired issues (if you haven't read it yet, of course).




回答2:


Here this is good example of Swing utilities that u can call :)

    /*
     * To change this template, choose Tools | Templates
     * and open the template in the editor.

    package com.verve.swinguti;

    import javax.swing.SwingUtilities;

    /**
     *
     * @author kishan
     */
    public class Utilities extends javax.swing.JFrame {

        /**
         * Creates new form Utilities
         */
        public Utilities() {
            initComponents();
        }

        /**
         * This method is called from within the constructor to initialize the form.
         * WARNING: Do NOT modify this code. The content of this method is always
         * regenerated by the Form Editor.
         */
        @SuppressWarnings("unchecked")
        // <editor-fold defaultstate="collapsed" desc="Generated Code">
        private void initComponents() {

            jPanel1 = new javax.swing.JPanel();
            jButton2 = new javax.swing.JButton();
            jButton1 = new javax.swing.JButton();

            setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

            jButton2.setText("jButton2");
            jButton2.addActionListener(new java.awt.event.ActionListener() {
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    jButton2ActionPerformed(evt);
                }
            });

            javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
            jPanel1.setLayout(jPanel1Layout);
            jPanel1Layout.setHorizontalGroup(
                jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(jPanel1Layout.createSequentialGroup()
                    .addGap(71, 71, 71)
                    .addComponent(jButton2)
                    .addContainerGap(155, Short.MAX_VALUE))
            );
            jPanel1Layout.setVerticalGroup(
                jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(jPanel1Layout.createSequentialGroup()
                    .addGap(118, 118, 118)
                    .addComponent(jButton2)
                    .addContainerGap(128, Short.MAX_VALUE))
            );

            jButton1.setText("jButton1");
            jButton1.addActionListener(new java.awt.event.ActionListener() {
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    jButton1ActionPerformed(evt);
                }
            });

            javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
            getContentPane().setLayout(layout);
            layout.setHorizontalGroup(
                layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(layout.createSequentialGroup()
                    .addContainerGap()
                    .addComponent(jButton1)
                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                    .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addContainerGap())
            );
            layout.setVerticalGroup(
                layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(layout.createSequentialGroup()
                    .addContainerGap()
                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                        .addGroup(layout.createSequentialGroup()
                            .addComponent(jButton1)
                            .addGap(0, 0, Short.MAX_VALUE))
                        .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                    .addContainerGap())
            );

            pack();
        }// </editor-fold>

        private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
            // TODO add your handling code here:
            try {
                SwingUtilities.invokeLater(new Runnable() {

                    @Override
                    public void run() {
                        try {
                            for (int i = 0; i < 10; i++) {
                                System.out.println("This is Good Example**");
                                Thread.sleep(2000);
                            }

                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                });

            } catch (Exception e) {
                e.printStackTrace();
            }

        }

        private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {
            // TODO add your handling code here:
            try {
                System.out.println("This is Second Button");

            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        /**
         * @param args the command line arguments
         */
        public static void main(String args[]) {
            /*
             * Set the Nimbus look and feel
             */
            //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
            /*
             * If Nimbus (introduced in Java SE 6) is not available, stay with the
             * default look and feel. For details see
             * http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
             */
            try {
                for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                    if ("Nimbus".equals(info.getName())) {
                        javax.swing.UIManager.setLookAndFeel(info.getClassName());
                        break;
                    }
                }
            } catch (ClassNotFoundException ex) {
                java.util.logging.Logger.getLogger(Utilities.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
            } catch (InstantiationException ex) {
                java.util.logging.Logger.getLogger(Utilities.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
            } catch (IllegalAccessException ex) {
                java.util.logging.Logger.getLogger(Utilities.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
            } catch (javax.swing.UnsupportedLookAndFeelException ex) {
                java.util.logging.Logger.getLogger(Utilities.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
            }
            //</editor-fold>

            /*
             * Create and display the form
             */
            java.awt.EventQueue.invokeLater(new Runnable() {

                public void run() {
                    new Utilities().setVisible(true);
                }
            });
        }
        // Variables declaration - do not modify
        private javax.swing.JButton jButton1;
        private javax.swing.JButton jButton2;
        private javax.swing.JPanel jPanel1;
        // End of variables declaration
    }



来源:https://stackoverflow.com/questions/24781402/execute-only-one-instance-of-swingworker

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!