在Java上遇到线程问题

时间:2014-10-09 00:44:31

标签: java multithreading

我有这个计算素数的程序。当按下停止时程序停止计算素数但是当我按GO时我需要程序继续其计算,但我无法找到如何再次启动我的线程。我尝试创建它的新实例但没有发生任何事情。这是我的代码:

public class PrimeApp1 extends JFrame {
protected JTextArea output;
protected JButton go;
protected JButton stop;
protected long counter = 2;
protected boolean stopComputation = false;
public boolean run = true;

protected boolean isPrime(long number) {
    long max = (long) Math.sqrt(number) + 1;
    for (long i = 2; i < max; i++) {
        if ((number % i) == 0) {
            return (false);
        }
    }
    return (true);
}

public class PrintPrimes extends Thread {

    @Override
    public void run() {
        // TODO Auto-generated method stub
        int primecount = 0;
        while (run == true) {
            if (isPrime(counter)) {
                primecount++;
                output.append(Long.toString(counter) + "\n");
                stop.setEnabled(true);
            }
            counter++;
        }
    }
}

public PrimeApp1() {
    super("Prime Numbers");
    final PrintPrimes print = new PrintPrimes();
    JPanel content = new JPanel();
    BorderLayout contentLayout = new BorderLayout();
    content.setLayout(contentLayout);

    output = new JTextArea();
    output.setEditable(false);
    JScrollPane scroller = new JScrollPane(output);
    content.add(scroller, BorderLayout.CENTER);

    JPanel buttonPane = new JPanel();
    FlowLayout buttonPaneLayout = new FlowLayout();
    buttonPane.setLayout(buttonPaneLayout);
    go = new JButton("Go");
    stop = new JButton("Stop");
    stop.setEnabled(false);
    buttonPane.add(go);
    buttonPane.add(stop);
    content.add(buttonPane, BorderLayout.SOUTH);

    go.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            print.start();
        }
    });

    stop.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            run = false;
        }
    });

    setContentPane(content);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setSize(600, 600);
    setVisible(true);
}

public static void main(String[] args) {
    new PrimeApp1();
}

}

3 个答案:

答案 0 :(得分:0)

我认为您的问题是您正在尝试启动已完成处理的线程。您只能启动一次线程,有关详细信息,请参阅here

您可能希望在该ActionListener中创建一个新的Thread对象并启动它,而不是在go动作侦听器中启动该线程。

这样的事情:

go.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {
        PrintPrimes print = new PrintPrimes();
        print.start();
    }
});

而不是在构造函数中创建最终的Thread对象。

答案 1 :(得分:0)

这取决于你想要达到的目标。如果你想“暂停”那么你应该按照@Junen的建议将线程的运行同步到按下按钮。

如果您想重新启动,可以执行以下操作:

public class PrintPrimes extends Thread {

    @Override
    public void run() {
        run = true; //You started the thread, hence when you enter run() it is running.
        int primecount = 0;
        while (run) {
            if (isPrime(counter)) {
                primecount++;
                output.append(Long.toString(counter) + "\n");
                stop.setEnabled(true);
            }
            counter++;
        }
    }
}

使print成为一个类对象并更改它:

go.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {
        print = new Thread(PrimeApp1.this);
        print.start();
    }
});

答案 2 :(得分:0)

如果您想暂停线程,请尝试以下操作。请注意run变量为volatile,因为主线程在技术上修改了它。

我还注意到在您的代码示例中,您正在从PrintPrimes线程修改UI。从单独创建的线程更新用户界面通常是不好的做法。

How to update java GUI from Thread?就此问题提供了一些解释。

How to Pause and Resume a Thread in Java from another Thread提供了有关停止和恢复线程的一些其他信息。在run方法中,我使用了类似的实现。

public class PrimeApp1 extends JFrame {
    protected JTextArea output;
    protected JButton go;
    protected JButton stop;
    protected boolean stopComputation = false;

    protected boolean isPrime(long number) {
        long max = (long) Math.sqrt(number) + 1;
        for (long i = 2; i < max; i++) {
            if ((number % i) == 0) {
                return (false);
            }
        }
        return (true);
    }

    public class PrintPrimes extends Thread {
        private int current = 2;
        private volatile boolean run = false;

        public PrintPrimes() {
        }

        public void run() {     
            while (true) {

                if (run == false) 
                    continue; // thread paused

                if (isPrime(current)) {
                    output.append(Long.toString(current) + "\n");                
                }
                current++;
            }
        }

        public void stopCount() {
            run = false;
        }

        public void startCount() {
            if (!run) {

                if (current == 2)
                    start(); // start initial thread 

                run = true;
            }
        }

    }

    public PrimeApp1() {
        super("Prime Numbers");
        final PrintPrimes print = new PrintPrimes();
        JPanel content = new JPanel();
        BorderLayout contentLayout = new BorderLayout();
        content.setLayout(contentLayout);

        output = new JTextArea();
        output.setEditable(false);
        JScrollPane scroller = new JScrollPane(output);
        content.add(scroller, BorderLayout.CENTER);

        JPanel buttonPane = new JPanel();
        FlowLayout buttonPaneLayout = new FlowLayout();
        buttonPane.setLayout(buttonPaneLayout);
        go = new JButton("Go");
        stop = new JButton("Stop");
        stop.setEnabled(false);
        buttonPane.add(go);
        buttonPane.add(stop);
        content.add(buttonPane, BorderLayout.SOUTH);

        go.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                go.setEnabled(false);
                stop.setEnabled(true);
                print.startCount();
            }
        });

        stop.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                stop.setEnabled(false);
                go.setEnabled(true);
                print.stopCount();
            }
        });

        setContentPane(content);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(600, 600);
        setVisible(true);
    }

    public static void main(String[] args) {
        new PrimeApp1();
    }
    }