您的位置:首页 > 编程语言 > Java开发

Java核心技术(多线程)五

2011-04-21 11:14 387 查看

线程与Swing

使用线程是为了提高程序的响应性能。当程序需要做某些耗时的工作时,应该启动另一个工作器线程而不是阻塞用户接口。Swing不是线程安全的,如果你试图在多个线程中操纵用户界面的元素,那么用户界面可能崩溃。将线程与Swing一起使用时,必须遵循:

*如果一个动作需要花费很长时间,在一个独立的工作器线程中做这件事不要在事件分配线程中做。

*除了事件分配线程,不要在任何线程中接触Swing组件。

应该使用EventQueue类的invokeLater和invokeAndWait方法使设置Swing界面的方法在事件分配线程中执行。invokeLater的方法立即返回,而run方法被异步执行;invokeAndWait方法等待直到run方法被确实执行过为止。

SwingWorker类是Swing工作器,是在专用线程中执行长时间GUI交互任务的抽象类。覆盖doInBackground方法来完成耗时的工作,不时地调用publish方法来报告工作进度。这一方法在工作器线程中执行。publish方法使得process方法在事件分配线程中执行来处理进度数据。当工作完成时,done方法在事件分配线程中被调用以便完成UI的更新。

public class SwingWorkerDemo
{
public static void main(String[] args) throws Exception
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
JFrame frame = new SwingWorkerFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
});
}
}
class SwingWorkerFrame extends JFrame
{
public SwingWorkerFrame()
{
chooser = new JFileChooser();
chooser.setCurrentDirectory(new File("."));
textArea = new JTextArea();
add(new JScrollPane(textArea));
setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
statusLine = new JLabel(" ");
add(statusLine, BorderLayout.SOUTH);
JMenuBar menuBar = new JMenuBar();
setJMenuBar(menuBar);
JMenu menu = new JMenu("File");
menuBar.add(menu);
openItem = new JMenuItem("Open");
menu.add(openItem);
openItem.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent event)
{
int result = chooser.showOpenDialog(null);
if (result == JFileChooser.APPROVE_OPTION)
{
textArea.setText("");
openItem.setEnabled(false);
textReader = new TextReader(chooser.getSelectedFile());
textReader.execute();
cancelItem.setEnabled(true);
}
}
});
cancelItem = new JMenuItem("Cancel");
menu.add(cancelItem);
cancelItem.setEnabled(false);
cancelItem.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent event)
{
textReader.cancel(true);
}
});
}
private class ProgressData
{
public int number;
public String line;
}
private class TextReader extends SwingWorker<StringBuilder, ProgressData>
{
public TextReader(File file)
{
this.file = file;
}
public StringBuilder doInBackground() throws IOException, InterruptedException
{
int lineNumber = 0;
Scanner in = new Scanner(new FileInputStream(file));
while (in.hasNextLine())
{
String line = in.nextLine();
lineNumber++;
text.append(line);
text.append("/n");
ProgressData data = new ProgressData();
data.number = lineNumber;
data.line = line;
publish(data);
Thread.sleep(1);
}
return text;
}
public void process(List<ProgressData> data)
{
if (isCancelled()) return;
StringBuilder b = new StringBuilder();
statusLine.setText("" + data.get(data.size() - 1).number);
for (ProgressData d : data)
{
b.append(d.line);
b.append("/n");
}
textArea.append(b.toString());
}
public void done()
{
try
{
StringBuilder result = get();
textArea.setText(result.toString());
statusLine.setText("Done");
}
catch (InterruptedException ex)
{
}
catch (CancellationException ex)
{
textArea.setText("");
statusLine.setText("Cancelled");
}
catch (ExecutionException ex)
{
statusLine.setText("" + ex.getCause());
}
cancelItem.setEnabled(false);
openItem.setEnabled(true);
}
private File file;
private StringBuilder text = new StringBuilder();
};
private JFileChooser chooser;
private JTextArea textArea;
private JLabel statusLine;
private JMenuItem openItem;
private JMenuItem cancelItem;
private SwingWorker<StringBuilder, ProgressData> textReader;
public static final int DEFAULT_WIDTH = 450;
public static final int DEFAULT_HEIGHT = 350;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: