我对线程很新,并且很长时间没有编写Java,所以请耐心等待。我有一个非常简单的GUI。它有一个计数器,一个状态标签和两个按钮,分别是启动和停止。
我想要它做的是使用counter
线程更新我的状态标签。当我点击开始时,它应该在0处开始计数器并且每second
递增一次,当我选择点击stop
时,它应该suspend
当前线程和wait
再次按下开始按钮。然而,每当我点击停止它只是暂停等待一秒钟并恢复计数。实际上我希望它保持暂停状态。我不确定为什么要这样做,在发布之前尝试搜索但没有得到任何结果。也可以随意批评你喜欢的任何事情。
以下是我所拥有的:
更新为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();
}
}
}
答案 0 :(得分:0)
基本上...
synchronized(this)
{
if(suspended)
{
if(getStatus())
wait();
resume();
}
}
getStatus
正在返回false
,因此它正在跳过wait
来电(因为t != null
。
我不确定为什么需要检查这个,但我可能会有enum
或其他标志返回更有意义的状态(例如RUNNING
,STOPPED
,{{ 1}} ......什么都有)
通过做类似的事情,我能够让它发挥作用。
PAUSED
代替。
尽管如此。我个人会考虑使用Swing synchronized(this)
{
if(suspended)
{
wait();
}
}
来完成所有这些工作,并在EDT的上下文中触发它的更新
即使你提出了建议的答案,它的行为方式仍然相同,它会暂停一小段时间并立即恢复
您修改了原始帖子中的代码,添加了
Timer
到t = new Thread(new CounterThread(this.threadName, this.countLabelName, this.statusLabelName));
方法,但您的UI代码已经引用了它正在与之交互的start
,所以现在您有两个同一个类的实例,一个在后台运行的实例离开,你的UI代码与之交互。
因此,当UI调用CounterThread
时,它不会更改实际运行的实例的suspend
状态
suspended
此外,我不知道在这种情况下使用Swing Timer会如何帮助我,因为等待没有实际的延迟
然后你显然不明白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");
int holder;
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();
}
});
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();
}
}
}
是如何运作的
Timer
现在,暂停和恢复问题都得到了解决