我花了好几个小时试图找出一项实验室练习的要求。

计划摘要

PrimeSeekerTask生成范围之间的质数。
PrimeSeekerDisplay是显示在PrimeSeekerTask中完成的工作的类。
PrimeSeekerTask应该在后台执行“大量”计算。我需要将SwingWorker扩展为PrimeSeekerTask

在程序运行期间,应该有PrimeSeekerTask的多个实例执行一小部分计算。我必须使用ExecutionService

另外,该程序应在单击开始按钮时启动,并在单击取消按钮时中断。

当我将任务作为单个背景SwingWorker运行时,它工作正常(如本屏幕快照所示)java - 具有ExecutionService和共享对象的SwingWorker-LMLPHP

但是程序规范是我应该运行许多SwingWorker对象。

我的问题


当我尝试使用ExecutionService时,程序挂起并消耗了几乎100%的CPU,笔记本电脑开始哭了。对于较小的数字,我会找到错误的百分比和质数数值。我猜有些同步错误,但我认为Atomic可以解决其中一些问题?
我的取消按钮不会中断任务。


任何帮助将不胜感激。

下面是我的真实尝试(为了使代码更短,我删除了导入)

public class PrimeSeekerDisplay extends JFrame
    implements ActionListener, PropertyChangeListener {

private JLabel topLabel;
private JTextArea textArea;
private JProgressBar progressBar;
private JButton startButton;
private JButton cancelButton;
private JLabel primesFoundLabel;

private final long max;
private final long chunkSize;
PrimeSeekerTask task = null;
private final int THREAD_NUMBER = 9;
ExecutorService executorService = Executors
        .newFixedThreadPool(THREAD_NUMBER);

/**
 *
 */
private static final long serialVersionUID = 6602966318374691217L;

/**
 *
 */
public PrimeSeekerDisplay(final long max, final long chunkSize) {
    super("Prime Seeker");
    this.max = max;
    this.chunkSize = chunkSize;
    initGui();

}

/*
 * initGui() creates all the components and lays them on the display
 */
private final void initGui() {

    // the top label
    topLabel = new JLabel("Primes in [1.." + String.valueOf(max) + "]");
    final JPanel topPanel = new JPanel();
    topPanel.add(topLabel);
    topPanel.setBorder(new EmptyBorder(5, 5, 5, 5));

    // the text area
    final JScrollPane textPane = createTextArea();

    // the progress bar
    progressBar = new JProgressBar(0, 100);
    progressBar.setStringPainted(true);
    progressBar.setBorder(BorderFactory.createLineBorder(Color.BLACK));

    // the buttons and items in the status pane
    startButton = createButton("Start");
    // enable this at the beginning of program.
    // This will be disabled when clicked
    startButton.setEnabled(true);

    cancelButton = createButton("Cancel");
    // Disable cancel before program starts.
    // Once program starts, this will be enabled
    cancelButton.setEnabled(false);

    // update this with number of primes found.
    // only print something here when atleast a prime is found
    primesFoundLabel = new JLabel();
    primesFoundLabel.setEnabled(false);

    final JPanel statusPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
    statusPanel.setBorder(new EmptyBorder(10, 0, 0, 0));
    statusPanel.add(startButton);
    statusPanel.add(cancelButton);
    statusPanel.add(primesFoundLabel);

    // Jpanel to hold all components
    final JPanel displayPanel = new JPanel();
    displayPanel.setLayout(new BoxLayout(displayPanel, BoxLayout.Y_AXIS));

    // add components to the display panel
    displayPanel.add(topPanel);
    displayPanel.add(textPane);
    displayPanel.add(progressBar);
    displayPanel.add(statusPanel);
    displayPanel.setBorder(new EmptyBorder(10, 10, 10, 10));

    // add the displayPanel to the frame
    add(displayPanel);
    setLocationRelativeTo(null);
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    pack();
}

/**
 * Create the text area embedded inside a ScrollPane
 *
 * @return a JScrollPane object
 */
private JScrollPane createTextArea() {
    textArea = new JTextArea(8, 40);
    textArea.setMargin(new Insets(5, 5, 5, 5));
    textArea.setLineWrap(true);
    textArea.setWrapStyleWord(true);
    textArea.setEditable(false);
    textArea.setLineWrap(true);
    textArea.setWrapStyleWord(true);
    final JScrollPane scrollPane = new JScrollPane(textArea);
    return scrollPane;
}

/**
 * A method for creating a JButton
 *
 * @param text The text to display on the button This value in lower
 *             case is also the actionCommand
 * @return A JButton with text, actionCommand, and action listener set
 */
private JButton createButton(final String text) {
    final JButton button = new JButton(text);
    button.setActionCommand(text.toLowerCase());
    button.addActionListener(this);
    return button;
}

/*
 * (non-Javadoc)
 *
 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.
 * ActionEvent)
 */
@Override
public void actionPerformed(ActionEvent e) {

    if (e.getActionCommand().equalsIgnoreCase("start")) {
        startButton.setEnabled(false);
        cancelButton.setEnabled(true);
        textArea.setText(null);
        primesFoundLabel.setText("Nothing found yet");

        // ####### Attempt to run many PrimeSeekerTasks fails ######
        // ****** i need help here and how to cancel the process///
        /*
        int chunk = (int) (max / chunkSize);

        System.out.println("chunk => " + chunk);
        int remainder = (int) (max % chunkSize);

        for (int index = 0; index < chunk; index++) {
            final long lower = index * chunkSize;
            final long upper = (index == chunk - 1
                    ? (lower + remainder + chunkSize)
                    : (lower + chunkSize));
            System.out.println("Index: " + index + " Lower: " + lower
                    + " upper: " + upper);
            PrimeSeekerTask primer = new PrimeSeekerTask(lower, upper);
            primer.addPropertyChangeListener(this);
            executorService.submit(primer);
        }

         */
        // =======
        //Running this works very well but it is not according to
        // program specs
        // ===========

          task = new PrimeSeekerTask(1, max);
          task.addPropertyChangeListener(this);
          task.execute();

    }
    if (e.getActionCommand().equalsIgnoreCase("cancel")) {
        if (task != null) {
            task.cancel(true);
        }
        startButton.setEnabled(true);
        cancelButton.setEnabled(false);
        //executorService.shutdownNow();
    }

}

/**
 * PrimeSeekerTask generatates prime numbers in a range and updates the
 * progressBar, textArea and primesFoundLabel
 *
 *
 * @author longb
 *
 */
private class PrimeSeekerTask extends SwingWorker<String, String> {

    private final long lowerRange;
    private final long upperRange;
    private final AtomicInteger progressMade = new AtomicInteger(0);
    private final AtomicLong primesFound = new AtomicLong(0);

    /**
     * @param upperRange
     * @param lowerRange
     */
    public PrimeSeekerTask(final long lowerRange, final long upperRange) {
        super();
        this.lowerRange = lowerRange;
        this.upperRange = upperRange;

    }

    /*
     * (non-Javadoc)
     *
     * @see javax.swing.SwingWorker#doInBackground()
     */
    @Override
    protected String doInBackground() throws Exception {
        while (!isCancelled()) {
            for (long lower = lowerRange; lower < upperRange; lower++) {

                if (isPrime(lower)) {
                    primesFound.getAndIncrement();
                    publish(String.valueOf(lower));
                    primesFoundLabel.setText(
                            "Primes found: " + primesFound.intValue());
                }
                progressMade.getAndIncrement();

                int progress = (int) (100 * (progressMade.intValue() + 1)
                        / upperRange);
                setProgress(progress);
            }

        }
        return "\n";
    }

    /*
     * (non-Javadoc)
     *
     * @see javax.swing.SwingWorker#process(java.util.List)
     */
    @Override
    protected void process(List<String> chunks) {
        for (String string : chunks) {
            textArea.append(string + ", ");
        }

    }

    /*
     * (non-Javadoc)
     *
     * @see javax.swing.SwingWorker#done()
     */
    @Override
    protected void done() {
        startButton.setEnabled(true);
        cancelButton.setEnabled(false);
    }
}

private boolean isPrime(final long number) {
    final long limit = (long) Math.sqrt(number) + 1;

    if (number < 2) {
        return false;
    }

    for (long i = 2; i < limit; ++i) {
        if ((number % i) == 0) {
            return false;
        }
    }
    return true;
}

/*
 * (non-Javadoc)
 *
 * @see java.beans.PropertyChangeListener#propertyChange(java.beans.
 * PropertyChangeEvent)
 */
@Override
public void propertyChange(PropertyChangeEvent evt) {
    if ("progress".equalsIgnoreCase(evt.getPropertyName())) {
        int progress = (int) evt.getNewValue();
        progressBar.setValue(progress);
    }
}

}


//在Run.java中

public class Run {

/**
 *
 */
public Run() {
    // TODO Auto-generated constructor stub
}

/**
 * @param args
 */
public static void main(String[] args) {

    if (args.length == 3) {
        for (int i = 0; i < args.length; i++) {
            System.out.println("arg#" + i + " : " + args[i]);
        }
        try {
            long max = Integer.valueOf(args[1]);
            long chunksize = Integer.valueOf(args[2]);
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    PrimeSeekerDisplay display = new PrimeSeekerDisplay(max,
                            chunksize);
                    display.setVisible(true);
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    } else {
        System.err.println("\nUsage: lab8 maxValue chunkSize\n");
    }
}

}


提前致谢。

最佳答案

这个答案与发布的第二个问题有关:“我的取消按钮不会中断任务”。
您有一个while循环,该循环应该在isCancelled()返回false时停止:

`while (! isCancelled())`


问题是,它后面是一个for循环。仅当for循环完成时才评估停止条件。
要克服它,只需添加

if (isCancelled() ) { break;}


for循环中。

第一个问题需要更多调查。
(请注意one question per post policy

09-11 05:51