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

计划摘要

PrimeSeekerTask生成一个范围之间的素数。 PrimeSeekerDisplay 是一个显示在 PrimeSeekerTask 中完成的工作的类。 PrimeSeekerTask 应该在后台进行“繁重”计算。我需要为 PrimeSeekerTask 扩展 SwingWorker

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

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

当我将任务作为单个后台 SwingWorker 运行时,它工作正常(如本屏幕截图所示)

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

我的问题。

  1. 当我尝试使用 ExecutionService 时,程序挂起并消耗了几乎 100% 的 CPU,笔记本电脑开始崩溃。对于小数字,我得到错误的百分比值和找到的质数。我猜想有一些同步错误,但我认为 Atomic 修复了其中的一些错误?

  2. 我的取消按钮不会中断任务。

任何形式的帮助将不胜感激。

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

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)


评论关闭
IT干货网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!