我對線程相當陌生,很長一段時間沒有寫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