我对线程相当陌生,很长一段时间没有写Java,因此请在这里与我联系。我有一个非常简单的GUI。它有一个计数器,一个状态标签和两个按钮,分别是开始和停止。通过线程更新图形用户界面
我想要做的是使用counter
线程更新我的状态标签。当我点击开始时,它应该在0处启动计数器,并且每增加一个second
,当我选择点击stop
时,它应该suspend
当前线程和wait
为开始按钮再次按下。然而,无论何时我停下来,它都会暂停等待一秒钟,然后重新开始计数。实际上,我希望它保持暂停状态。我不确定为什么会这样做,在发布之前尝试搜索它,但什么都没有。也可以随意批评任何你想要的东西。
这是我有:
更新,如PER @ MadProgrammer的答案。
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import static javax.swing.JFrame.EXIT_ON_CLOSE;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
public class main extends JFrame
{
JLabel countLabel = new JLabel("0");
JLabel statusLabel = new JLabel("Task not completed.");
JButton startButton = new JButton("Start");
JButton stopButton = new JButton("Stop");
CounterThread worker = new CounterThread("worker", countLabel, statusLabel);
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new Main("Counter Demo");
}
});
}
public Main(String title) {
super(title);
setLayout(new GridBagLayout());
countLabel.setFont(new Font("serif", Font.BOLD, 28));
GridBagConstraints gc = new GridBagConstraints();
gc.fill = GridBagConstraints.NONE;
gc.gridx = 0;
gc.gridy = 0;
gc.weightx = 1;
gc.weighty = 1;
add(countLabel, gc);
gc.gridx = 0;
gc.gridy = 1;
gc.weightx = 1;
gc.weighty = 1;
add(statusLabel, gc);
gc.gridx = 0;
gc.gridy = 2;
gc.weightx = 1;
gc.weighty = 1;
add(startButton, gc);
gc.gridx = 0;
gc.gridy = 3;
gc.weightx = 1;
gc.weighty = 1;
add(stopButton, gc);
startButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
worker.start();
//notify();
}
});
stopButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
worker.suspend();
}
});
setSize(200, 400);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
}
public class CounterThread implements Runnable {
public Thread t;
public String threadName;
boolean suspended = false;
JLabel countLabelName;
JLabel statusLabelName;
CounterThread(String name, JLabel cLabel, JLabel sLabel) {
this.threadName = name;
this.countLabelName = cLabel;
this.statusLabelName = sLabel;
}
public void run() {
try {
// Simulate doing something useful.
for (int i = 0; i <= 10; i++) {
synchronized (this) {
if (suspended)
{
wait();
}
}
final int count = i;
SwingUtilities.invokeLater(new Runnable() {
public void run() {
countLabelName.setText(Integer.toString(count));
}
});
Thread.sleep(1000);
}
} catch (InterruptedException e) {
}
SwingUtilities.invokeLater(new Runnable() {
public void run() {
statusLabelName.setText("Completed.");
}
});
this.start();
}
public boolean getStatus() {
return t == null;
}
public void start() {
if (getStatus()) {
//t = new Thread(new CounterThread(this.threadName, this.countLabelName, this.statusLabelName));
t = new Thread(this);
t.start();
}
}
public void suspend() {
statusLabelName.setText("Task is paused");
suspended = true;
}
//create an object whose only purpose is to synchronize
synchronized void resume() {
statusLabelName.setText("Task has resumed");
suspended = false;
this.notify();
}
}
}
最好的办法是审查甲骨文的Swing和线程教程,并检查了相关摆动实用工具类,其中一些要导入但从不使用。同样,你似乎知道java.util.concurrent,但没有使用它。避免直接使用同步原语,'notify'等。清理你的代码及其缩进,并且 - 你有一个实现了runnable但包含一个线程的类,并启动一个线程,很难跟踪正在发生的事情,可能是因为你也是。 – pvg
除非你有特别需要做一些额外的处理的背景下,我会考虑在使用Swing的在看看'Timer'代替 – MadProgrammer
'布尔暂停= FALSE;'或许也会被标记'volatile'(或使用一个'AtomicBoolean') – MadProgrammer