【问题标题】:Make a recursive method pause in every recurse and continue with click在每个递归中暂停递归方法并继续单击
【发布时间】:2009-07-26 10:55:58
【问题描述】:

我有一个递归方法,可以在每次递归中更改变量的值,然后在 JPanel 上显示该值,然后我想暂停 (这是我的问题),直到我单击(它会在每个新的递归中暂停)。然后当我点击这个方法时继续做下一次递归。

以下代码只是我的真实程序的结构以及我如何尝试实现它。我已经尝试了很多方法来使用线程和执行器来做这件事,但我失败了。

我创建了 2 个类,PanelToBeClicked 类是一个 JPanel 并具有递归方法,以及一个 PanelMouseListener 类收集点击。

以下代码完全没有线程和执行程序。如果有人可以在这里添加一些代码行来演示正确的方法,我将不胜感激,或者 给我一些关于如何实现它的线索。

代码如下:

import java.awt.*;
import javax.swing.*;

public class PanelToBeClicked extends JPanel {
    int counter;

    public PanelToBeClicked() {
     super();
     setPreferredSize(new Dimension(100,100));
     addMouseListener(new PanelMouseListener(this));
}

@Override
protected void paintComponent(Graphics g){
    super.paintComponent(g);
    g.drawString(""  + counter, 10, 10);
}

public void recursiveMethod(){
    counter++;
    repaint();     

    /*
     * Pause/wait until the panel is clicked so you proceed the recursions
     * MISSING CODE HERE. I tried thread.sleep 
     * but I had a monitor exception 
    */

    if (counter <10)recursiveMethod();
}

public static void main(String[] args) {
    final JFrame frame = new JFrame("How can i do that?");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.add(new PanelToBeClicked());

    SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
            frame.pack();
            frame.setVisible(true);
        }
    });
}
}

听者:

public class PanelMouseListener extends MouseAdapter {
   private PanelToBeClicked panelToBeClicked;

    public PanelMouseListener(PanelToBeClicked panelToBeClicked) {
            this.panelToBeClicked = panelToBeClicked;
    }

    @Override
    public void mouseClicked(MouseEvent e) {

    /*
     *  start the method PanelToBeClicked.recursiveMethod()... 
    */
    panelToBeClicked.recursiveMethod();

    /*
     *  if the method is already running  and it is not paused do nothing. 
     *  ** MISSING CODE
     *  if the method is running and is  paused then  make the method to continue the recursions 
     *   **MISSING CODE  */

    }

}

【问题讨论】:

    标签: java multithreading


    【解决方案1】:

    不要忘记您的 Swing Panel 将在单独的线程中执行。

    您需要等待一个监视器对象(例如,在 2 个线程之间共享的对象),然后单击面板将向该对象发送通知。递归方法需要等待监视器收到面板上的点击动作通知。

    在伪代码中(例外等省略)

    Object monitor = new Object();
    
    void recursiveMethod() {
       // do stuff and then wait...
       synchronized (monitor) {
          monitor.wait();
       }
    }
    
    void doClick() {
       synchronized (monitor) {
          monitor.notify();
       }
    }
    

    有关详细信息,请参阅 Java Guarded Objects 教程。

    【讨论】:

    • Thnx for you anseer... 我在设置通用对象监视器时遇到问题.. 我总是得到一个 illigalMonitorException.... 另外调用面板是什么意思?它与java反射有关吗?我的想法是能够在 recursiceMethod 中使用 thread.sleep() 方法(但我得到一个监视器异常作为 expecetd ... :( ),然后在 listner 类的 mouseClicked 处使用 thread.notify() /跨度>
    • 编辑显示伪代码。请注意,要等待/通知您需要在对象上同步
    • 感谢您的链接和答案。我已经尝试过你所说的,它几乎..工作了。我在递归方法中使用了 monitor.wait(),在 mouseClicked 方法中使用了 monitor.notify9) ..但是程序停止了...甚至JFrame的关闭按钮都不起作用。我虽然这一定会发生,因为主线程在monitor.wait()调用时被挂起......所以我把recursiveMethod放在一个新线程中并且它工作完美......问题是在每个递归中都有一个新线程已创建..我读过这不是正确的方法..所以..你知道如何使代码更干净吗?
    • 我会做一个线程转储(Ctrl+break),看看有什么问题。线程转储会告诉你什么在等待什么
    • 我在 monitor.wait() 之前做了一个 thread.CurrentThread(),结果是 Thread[AWT-EventQueue-0,6,main]
    【解决方案2】:

    只是想举一个Java 5+锁+条件方式的例子:

    package gui;
    
    import java.awt.Container;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.util.concurrent.locks.Condition;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    import javax.swing.GroupLayout;
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.SwingUtilities;
    import javax.swing.SwingWorker;
    import javax.swing.GroupLayout.Alignment;
    
    public class RecursiveContinue extends JFrame {
        private static final long serialVersionUID = 7149607943058112216L;
        JLabel value;
        JButton next;
        volatile SwingWorker<Void, Void> worker;
        Lock lock = new ReentrantLock();
        Condition cond = lock.newCondition();
        boolean continueFlag;
        public RecursiveContinue() {
            super("Recursive Continue Example");
            setDefaultCloseOperation(DISPOSE_ON_CLOSE);
            value = new JLabel("Recursion depth: None");
            next = new JButton("Next");
            next.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    doNextClick();
                }
            });
            Container c = getContentPane();
            GroupLayout gl = new GroupLayout(c);
            c.setLayout(gl);
            gl.setAutoCreateContainerGaps(true);
            gl.setAutoCreateGaps(true);
    
            gl.setHorizontalGroup(
                gl.createSequentialGroup()
                .addComponent(value)
                .addComponent(next)
            );
            gl.setVerticalGroup(
                gl.createParallelGroup(Alignment.BASELINE)
                .addComponent(value)
                .addComponent(next)
            );
    
            pack();
            setLocationRelativeTo(null);
        }
    
        void doNextClick() {
            if (worker == null) {
                worker = new SwingWorker<Void, Void>() {
                    @Override
                    protected Void doInBackground() throws Exception {
                        doRecursiveAction(0);
                        SwingUtilities.invokeLater(new Runnable() {
                            @Override
                            public void run() {
                                value.setText("Recursive level: Done");
                            }
                        });
                        worker = null;
                        return null;
                    }
                };
                worker.execute();
            } else {
                signal();
            }
    
        }
        void signal() {
            lock.lock();
            try {
                continueFlag = true;
                cond.signalAll();
            } finally {
                lock.unlock();
            }
        }
        void await() {
            lock.lock();
            try {
                while (!continueFlag) {
                    cond.await();
                }
                continueFlag = false;
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            } finally {
                lock.unlock();
            }
        }
        void doRecursiveAction(final int depth) {
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    value.setText("Recursive level: " + depth);
                }
            });
            await();
            if (depth < 10) {
                doRecursiveAction(depth + 1);
            }
        }
        /**
         * @param args
         */
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    new RecursiveContinue().setVisible(true);
                }
            });
        }
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-08-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-15
      • 2012-05-26
      • 1970-01-01
      相关资源
      最近更新 更多