Я часами боролся, пытаясь выяснить одно из требований лабораторного упражнения.
Краткое содержание программы
Класс PrimeSeekerTask
генерирует простые числа между диапазонами.
PrimeSeekerDisplay
- это класс, который отображает работу, выполненную в PrimeSeekerTask
.
PrimeSeekerTask предназначен для выполнения «тяжелых» вычислений в фоновом режиме. Я обязан продлить SwingWorker
для PrimeSeekerTask
.
Во время выполнения программы должно быть несколько экземпляров PrimeSeekerTask
, которые выполняют небольшую часть вычислений. Я обязан использовать ExecutionService
.
Кроме того, программа должна запускаться при нажатии кнопки запуска и прерываться при нажатии кнопки отмены.
Когда я запускаю задачу как один фон SwingWorker
, она отлично работает (как на этом снимке экрана)
, но спецификация программы такова, что я должен был запустить много SwingWorker
объектов.
Мои проблемы.
Когда я пытаюсь использовать ExecutionService
, программа зависает и потребляет почти 100% моего процессора, и ноутбук начинает плакать. Для небольших чисел, я получаю неправильные значения для процента и найденных простых чисел. Я думаю, некоторые ошибки синхронизации, но я подумал, 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");
}
}
}
Заранее спасибо.