【发布时间】:2016-11-22 12:46:33
【问题描述】:
我想了解一些关于一个线程一次调用swing方法的信息。
编辑: 我使用 Java 7。
我看到了以下话题:
Thread Safety of JTextArea.append
我开发了一个迷你秋千应用程序。
这是我的主类,它是一个线程安全的类。 我调用 SwingUtilities.invokeLater 方法使其成为线程安全类。
主类:
package swingex;
import javax.swing.SwingUtilities;
public final class MainClass extends Thread {
public static void main(String[] _args) {
SwingUtilities.invokeLater(new MainClass());
}
@Override
public void run() {
new MainWindow();
}
}
这是一个继承自 JFrame 的类。 我在内容窗格中放置了一个文本区域和一个按钮。
主窗口:
package swingex;
import java.awt.Dimension;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
public final class MainWindow extends JFrame {
private JTextArea textArea = new JTextArea(32,32);
//AddText inherits from Thread class
private AddText thread = new AddText(textArea);
public MainWindow() {
JPanel panel_ = new JPanel();
panel_.setLayout(new BoxLayout(panel_, BoxLayout.PAGE_AXIS));
JScrollPane scr_ = new JScrollPane(textArea);
scr_.setPreferredSize(new Dimension(128, 128));
panel_.add(scr_);
//The button is used for adding rows in the text area
JButton button_ = new JButton("Add rows");
//Adding the event
button_.addActionListener(new AddTextEvent(this));
panel_.add(button_);
setContentPane(panel_);
setDefaultCloseOperation(EXIT_ON_CLOSE);
pack();
setVisible(true);
}
//Called by actionPerformed method
public void setText() {
if (thread.isAlive()) {
//prevent from setting the text area by multi threading
return;
}
//For avoiding issues, the text area is affected by less than two threads.
thread = new AddText(textArea);
thread.start();
}
}
单击按钮使线程休眠 5 秒,然后线程将 200 行添加到文本区域。 添加文本:
package swingex;
import java.awt.Rectangle;
import javax.swing.JTextArea;
import javax.swing.text.BadLocationException;
public final class AddText extends Thread {
private JTextArea textArea;
public AddText(JTextArea _textArea) {
textArea = _textArea;
}
@Override
public void run() {
try {
Thread.sleep(5000);
} catch (InterruptedException _0) {
_0.printStackTrace();
}
//Only one thread can access the code
for (int i = 0; i < 200; i++) {
textArea.append("Text"+i+"\n");
}
int endPosition_ = textArea.getDocument().getLength();
Rectangle bottom_;
try {
bottom_ = textArea.modelToView(endPosition_);
textArea.scrollRectToVisible(bottom_);
} catch (BadLocationException _0) {
_0.printStackTrace();
}
}
}
该类实现ActionListener,用于点击按钮。
添加文本事件:
package swingex;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public final class AddTextEvent implements ActionListener {
private MainWindow window;
public AddTextEvent(MainWindow _window) {
window = _window;
}
@Override
public void actionPerformed(ActionEvent _e) {
window.setText();
}
}
提前谢谢你。
编辑 2:我的“新线程”类如下: (其他类保持不变。)
package swingex;
import java.awt.Rectangle;
import javax.swing.JTextArea;
import javax.swing.SwingWorker;
import javax.swing.text.BadLocationException;
/**Now the class AddText inherits from SwingWorker*/
public final class AddText extends SwingWorker<Void, Void> {
private JTextArea textArea;
public AddText(JTextArea _textArea) {
textArea = _textArea;
}
/**The equivalent in the class Thread*/
public void start() {
execute();
}
@Override
public Void doInBackground() {
try {
Thread.sleep(5000);
} catch (InterruptedException _0) {
_0.printStackTrace();
}
for (int i = 0; i < 200; i++) {
textArea.append("Text"+i+"\n");
}
int endPosition_ = textArea.getDocument().getLength();
Rectangle bottom_;
try {
bottom_ = textArea.modelToView(endPosition_);
textArea.scrollRectToVisible(bottom_);
} catch (BadLocationException _0) {
_0.printStackTrace();
}
return null;
}
/**The equivalent in the class Thread*/
public boolean isAlive() {
return !isDone() || !isCancelled();
}
}
编辑 3:它是一个继承自“swing”组件的自定义类:
我的自定义方法是否“线程安全”?
MyTextArea:
package swingex;
import javax.swing.JTextArea;
public class MyTextArea extends JTextArea {
private String aField = "";
public String getaField() {
return aField;
}
public void setaField(String _aField) {
aField = _aField;
}
}
现在,我使用 SwingWorker 的“doInBackground”方法中的 SwingUtilities 的“invokeLater”方法
【问题讨论】:
-
为什么不使用 Swing
Timer? -
@Catalina Island:我想用Thread类的“sleep”方法来模拟长时间的治疗。
-
您可以使用
SwingWorker或invokeLater()。 -
不,
doInBackground将在后台线程中调用,这是您进行长时间处理的地方(如睡眠...),因此它不会阻塞 UI。您应该在done方法中更新您的 UI。查看 Holger 评论中的文档。 -
@grape_mao:我看到Marek Blotny的回答:What is meant by thread safe code ?,如果只有两个或多个线程调用append方法,那么可能有问题。
标签: java multithreading swing thread-safety