我正在学习线程并尝试调整此tutorial和此tutorial。
但是,有些东西不对,因为线程没有继续经过for循环的一次迭代,并且按钮的actionListener实现不起作用。最初,我让线程以这种方式工作:
private class EstiPi implements Runnable {
final int numDisplay = 5000000;
long numEstimation;
long numTouchCircle;
public volatile boolean timeToQuit = false;
private EstiPiGui gui;
double estiPi;
public EstiPi() {
}
@Override
public void run() {
System.out.println("Thread started");
while (!timeToQuit) {
for (int i = 0; i < numDisplay; i++) {
double x = Math.random();
double y = Math.random();
numEstimation++;
if (x * x + y * y < 1) {
numTouchCircle++;
}
}
System.out.println(numEstimation);
System.out.println(numTouchCircle);
estiPi = ((double) numTouchCircle / numEstimation) * 4;
estiPiLabel.setText(String.valueOf(estiPi));
}
}
}
但现在我正在尝试添加GUI来暂停和恢复
我的runnable类集成按钮控件:
private class EstiPi implements Runnable {
final int numDisplay = 5000000;
long numEstimation;
long numTouchCircle;
double estiPi;
public EstiPi() {
}
@Override
public void run() {
System.out.println("Thread started");
try {
for (int i = 0; i < numDisplay; i++) {
double x = Math.random();
double y = Math.random();
numEstimation++;
if (x * x + y * y < 1) {
numTouchCircle++;
}
}
System.out.println(numEstimation);
System.out.println(numTouchCircle);
estiPi = ((double) numTouchCircle / numEstimation) * 4;
estiPiLabel.setText(String.valueOf(estiPi));
synchronized (this) {
while (!running) {
wait();
}
}
} catch (InterruptedException e) {
System.out.println("Interrupted");
}
}
}
以这种方式执行按钮操作:
private void runPauseButtonActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
if (running) {
runPauseButton.setText("Run");
running = false;
} else {
runPauseButton.setText("Pause");
synchronized (piThread) {
running = true;
piThread.notify();
}
}
}
启动gui组件时启动线程:
public EstiPiGui() {
initComponents();
piRunner = new EstiPi();
piThread = new Thread(piRunner);
add(estiPiLabel);
add(estiCountLabel);
piThread.start();
}
我的按钮和标签:
private javax.swing.JLabel estiCountLabel;
private javax.swing.JLabel estiPiLabel;
private javax.swing.JButton runPauseButton;
更新 在集成SO用户的答案并添加while(true)块后,按下标有“Run”的按钮可更改标签。但是,按暂停不会做任何事情。
奇怪的是,即使我没有按下暂停按钮,mLock.wait()之后的print语句也会输出。 运行变量是否在我看不到的地方变为假?
public void run() {
System.out.println("Thread started");
while (true) {
for (int i = 0; i < numDisplay; i++) {
try {
synchronized (mLock) {
while (!running) {
mLock.wait();
System.out.println("mLock : waiting");
System.out.println(running);
}
}
} catch (InterruptedException e) {
}
double x = Math.random();
double y = Math.random();
numEstimation++;
if (x * x + y * y < 1) {
numTouchCircle++;
}
}
System.out.println(numEstimation);
System.out.println(numTouchCircle);
estiPi = ((double) numTouchCircle / numEstimation) * 4;
estiPiLabel.setText(String.valueOf(estiPi));
}
}
按钮操作和初始化变量:
public class EstiPiGui extends javax.swing.JFrame {
static EstiPiGui myGui;
public volatile boolean running;
EstiPi piRunner;
Thread piThread;
public static final Object mLock = new Object();
/**
* Creates new form EstPiGui
*/
public EstiPiGui() {
initComponents();
piRunner = new EstiPi();
piThread = new Thread(piRunner);
add(estiPiLabel);
add(estiCountLabel);
piThread.start();
}
private void runPauseButtonActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
if (running) {
runPauseButton.setText("Run");
synchronized (mLock) {
running = false;
}
}
if (!running) {
runPauseButton.setText("Pause");
synchronized (mLock) {
running = true;
mLock.notify();
}
}
}
/**
* @param args the command line arguments
*/
public static void main(String args[]) {
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
myGui = new EstiPiGui();
myGui.setVisible(true);
}
});
}
private class EstiPi implements Runnable {
final int numDisplay = 5000000;
long numEstimation;
long numTouchCircle;
//public volatile boolean running;
private EstiPiGui gui;
double estiPi;
public EstiPi() {
}
@Override
public void run() {
System.out.println("Thread started");
while (true) {
for (int i = 0; i < numDisplay; i++) {
try {
synchronized (mLock) {
while (!running) {
mLock.wait();
System.out.println("mLock : waiting");
}
}
} catch (InterruptedException e) {
}
double x = Math.random();
double y = Math.random();
numEstimation++;
if (x * x + y * y < 1) {
numTouchCircle++;
}
}
System.out.println(numEstimation);
System.out.println(numTouchCircle);
estiPi = ((double) numTouchCircle / numEstimation) * 4;
estiPiLabel.setText(String.valueOf(estiPi));
estiCountLabel.setText(String.valueOf(numEstimation));
}
}
}
// Variables declaration - do not modify
private javax.swing.JLabel estiCountLabel;
private javax.swing.JLabel estiPiLabel;
private javax.swing.JButton runPauseButton;
// End of variables declaration
}
答案 0 :(得分:2)
移动以下代码块
synchronized (this) {
while (!running) {
wait();
}
}
进入for
循环块。
for (int i = 0; i < numDisplay; i++) {
try {
synchronized (mLock) {
while (!running) {
mLock.wait();
}
}
} catch(InterruptedException e) {
//do nothing just continue
}
double x = Math.random();
double y = Math.random();
numEstimation++;
if (x * x + y * y < 1) {
numTouchCircle++;
}
}
System.out.println(numEstimation);
System.out.println(numTouchCircle);
estiPi = ((double) numTouchCircle / numEstimation) * 4;
estiPiLabel.setText(String.valueOf(estiPi));
<强>更新强>
正如克里斯所指出的,需要使用相同的参考来执行锁定。
在简历按钮中单击,将其更改为此类。
if (!running) {
synchronized (mLock) {
running = true;
mLock.notify();
}
}
和mLock
是一个可以从piThread或主线程访问的全局对象。
public static final Object mLock = new Object();
<强>更新强>
您运行/暂停按钮不起作用,因为您的if
条件检查。当running
为真时,执行将首先进入if
并将running
设置为false。现在running == false
。执行仍在继续,当它即将执行第二个if
时,running = false
因此条件(!running)
返回true,因此它进入第二个if
并设置running
为true并调用mLock.notify()
,因此工作线程永远不会暂停。
if (running) {
runPauseButton.setText("Run");
synchronized (mLock) {
running = false;
}
}
if (!running) {
runPauseButton.setText("Pause");
synchronized (mLock) {
running = true;
mLock.notify();
}
}
将其更改为if .. else
阻止
if (running) {
runPauseButton.setText("Run");
synchronized (mLock) {
running = false;
}
} else {
runPauseButton.setText("Pause");
synchronized (mLock) {
running = true;
mLock.notify();
}
}