正确使用线程让我很难过

时间:2015-02-16 08:31:26

标签: java multithreading

我试图学习如何使用线程。我已经使用API​​和文档做了一个例子试图让它尽可能简单。表单2按钮和进度条更新我无法从API示例中使用它。首先我的基本Form然后是应该正确运行线程的类。当我点击一个按钮时,它会冻结GUI并且不会更新进度条,有些人提到我阻止了GUI线程......这使我很困惑。有人能告诉我哪里出错了。

package mythreadtry;

/**
 *
 * @author brett
 */
public class MyThreadMainGui extends javax.swing.JDialog {

    /**
     * Creates new form MyThreadMainGui
     */
    public MyThreadMainGui(java.awt.Frame parent, boolean modal) {
        super(parent, modal);
        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() {

        jButton1 = new javax.swing.JButton();
        jButton2 = new javax.swing.JButton();
        jProgressBar1 = new javax.swing.JProgressBar();

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);

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

        jButton2.setText("jButton2");
        jButton2.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton2ActionPerformed(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()
                .addGap(36, 36, 36)
                .addComponent(jButton1)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(jButton2)
                .addContainerGap(208, Short.MAX_VALUE))
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jProgressBar1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addContainerGap(210, Short.MAX_VALUE)
                .addComponent(jProgressBar1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(18, 18, 18)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jButton1)
                    .addComponent(jButton2))
                .addGap(35, 35, 35))
        );

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

    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {                                         
        // TODO add your handling code here:
        MyThreadTry mmt = new MyThreadTry();
        mmt.doit(null);
    }                                        

    private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {                                         
        // TODO add your handling code here:
         MyThreadTry mmt = new MyThreadTry();
        mmt.doit(null);
    }                                        
//    
    public void updateProgress(int newValue){
        jProgressBar1.setValue(newValue);
    }
    /**
     * @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(MyThreadMainGui.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(MyThreadMainGui.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(MyThreadMainGui.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(MyThreadMainGui.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        /* Create and display the dialog */
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                MyThreadMainGui dialog = new MyThreadMainGui(new javax.swing.JFrame(), true);
                dialog.addWindowListener(new java.awt.event.WindowAdapter() {
                    @Override
                    public void windowClosing(java.awt.event.WindowEvent e) {
                        System.exit(0);
                    }
                });
                dialog.setVisible(true);
            }
        });
    }

    // Variables declaration - do not modify                     
    private javax.swing.JButton jButton1;
    private javax.swing.JButton jButton2;
    private javax.swing.JProgressBar jProgressBar1;
    // End of variables declaration                   
}

接下来是我尝试一个线程......我希望这很简单。我把整个表格都包括在内,这样你们就可以告诉我如何试着打电话给班级。

package mythreadtry;

import java.awt.event.MouseEvent;

/**
 *
 * @author brett
 */
public class MyThreadTry implements Runnable{
 long minPrime;
  volatile Thread p =  new Thread();
  volatile boolean threadSuspended;
         MyThreadTry() {
             int times = 100000; 
             for(int i = 0; i <= times; i++ ){
                 this.minPrime = i;
                 System.out.println(this.minPrime);
                 MyThreadMainGui myg = new MyThreadMainGui(null, threadSuspended);
                 myg.updateProgress((int)this.minPrime);
             }

         }
     public void doit(String[] args) {
       p.start();

    }
         public void run() {
            Thread thisThread = Thread.currentThread();
            threadSuspended = true;
        while (p == thisThread) {
            try {
                p.sleep(500);

                synchronized(this) {
                    while (threadSuspended && p==thisThread)
                        wait();
                }
            } catch (InterruptedException e){
            }
        }
    }
public synchronized void mousePressed(MouseEvent e) {
        e.consume();

        threadSuspended = !threadSuspended;

        if (!threadSuspended)
            notify();
    }
    public synchronized void stop() {
        this.p = null;
        notify();
    }
    /**
     * @param args the command line arguments
     */


}

1 个答案:

答案 0 :(得分:3)

  

当我点击一个按钮时,它会冻结GUI并且不会更新进度条

当您按下其中一个按钮时,您将创建一个MyThreadTry

的实例
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {                                         
    // TODO add your handling code here:
    MyThreadTry mmt = new MyThreadTry();
    mmt.doit(null);
}  

MyThreadTry的构造函数然后循环100,000次,创建了100,000个MyThreadMainGUI的实例

MyThreadTry() {
     int times = 100000; 
     for(int i = 0; i <= times; i++ ){
         this.minPrime = i;
         System.out.println(this.minPrime);
         MyThreadMainGui myg = new MyThreadMainGui(null, threadSuspended);
         myg.updateProgress((int)this.minPrime);
     }
 }

所有这些都在事件调度线程的上下文中。 EDT负责处理事件队列,其中包括绘制事件。

这意味着在此方法实际完成之前,无法更新任何内容。

有关详细信息,请参阅Concurrency in Swing

当构造函数&#34;最终&#34;返回,您拨打doit,呼叫p.start。但是,既然您没有覆盖p的{​​{1}}方法,也没有提供run,那么它什么都不做......

已更新为可运行示例

我的偏好是在这些情况下使用Runnable,但由于我们正在谈论线程,所以这里是一个线程版本。

SwingWorker

确保您有时间阅读Concurrency in Java,特别是关于锁定的部分和Concurrency in Swing