下面是一个小程序,它使用Newton-Raphson方法以高精度找出平方根。
除了SwingWorker
之外,一切似乎都按预期工作。运行此应用程序时,应用程序将冻结,并且在SwingWorker
完成其任务之前无法使用。但是,我认为SwingWorker
的目的是避免这种情况。
有人可以帮我解决问题吗?
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.concurrent.ExecutionException;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSlider;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingWorker;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.text.DefaultCaret;
import net.miginfocom.swing.MigLayout;
@SuppressWarnings("serial")
public class SquareRoot extends JFrame {
private BigDecimal SQRT_DIG = new BigDecimal(150);
private SquareRoot() {
super("Square Rooter");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
createLayout(this);
pack();
setLocationRelativeTo(null);
setVisible(true);
}
private void createLayout(JFrame addTo) {
JPanel rootPanel = new JPanel(new MigLayout("wrap", "grow", ""));
JLabel acc = new JLabel("Accuracy: " + SQRT_DIG);
JSlider accSlide = new JSlider(1, 1000000, 150);
JLabel numRoot = new JLabel("Number to Square Root");
JTextField num = new JTextField();
JButton root = new JButton("Root");
JLabel ansRoot = new JLabel("Answer");
JTextArea ans = new JTextArea();
JScrollPane ansHolder = new JScrollPane(ans);
accSlide.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent arg0) {
SQRT_DIG = new BigDecimal(accSlide.getValue());
acc.setText("Accuracy: " + SQRT_DIG);
}
});
rootPanel.add(acc);
rootPanel.add(accSlide, "grow");
root.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
ans.setText("Please Wait");
new SwingWorker<BigDecimal, Object>() {
@Override
protected BigDecimal doInBackground() throws Exception {
return bigSqrt(new BigDecimal(num.getText()));
}
@Override
protected void done() {
try {
ans.setText(get().toPlainString());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
}.run();
}
});
rootPanel.add(numRoot);
rootPanel.add(num, "grow");
rootPanel.add(root, "right");
ans.setEditable(false);
((DefaultCaret) ans.getCaret()).setUpdatePolicy(DefaultCaret.NEVER_UPDATE);
ansHolder.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
rootPanel.add(ansRoot);
rootPanel.add(ansHolder, "grow");
addTo.add(rootPanel);
}
private BigDecimal sqrtNewtonRaphson(BigDecimal c, BigDecimal xn, BigDecimal precision) {
BigDecimal fx = xn.pow(2).add(c.negate());
BigDecimal fpx = xn.multiply(new BigDecimal(2));
BigDecimal xn1 = fx.divide(fpx,2*SQRT_DIG.intValue(),RoundingMode.HALF_DOWN);
xn1 = xn.add(xn1.negate());
BigDecimal currentSquare = xn1.pow(2);
BigDecimal currentPrecision = currentSquare.subtract(c);
currentPrecision = currentPrecision.abs();
if (currentPrecision.compareTo(precision) <= -1)
return xn1;
return sqrtNewtonRaphson(c, xn1, precision);
}
private BigDecimal bigSqrt(BigDecimal c) {
return sqrtNewtonRaphson(c, new BigDecimal(1), new BigDecimal(1).divide(new BigDecimal(10).pow(SQRT_DIG.intValue())));
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> new SquareRoot());
}
}
答案 0 :(得分:4)
我相信您的问题是由于您使用run()
方法来执行SpringWorker。使用execute()
代替将确保spring worker将在一个工作线程中运行。