在每个递归中使递归方法暂停并继续单击

时间:2009-07-26 10:55:58

标签: java multithreading

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

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

我创建了两个类,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  */

    }

}

2 个答案:

答案 0 :(得分:0)

不要忘记你的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教程。

答案 1 :(得分:0)

只是想举一个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);
            }
        });
    }

}