java学习之浅谈多线程4--SwingWorker
来源:互联网 发布:xenomai编程笔记 编辑:程序博客网 时间:2024/04/30 20:55
GUI事件处理和绘图代码在一个被称为事件分发线程的特殊线程中执行。如果一个事件需要很长的时间处理,线程就不能顾及到队列中的其他任务。为了解决这个问题,可以运行费时的任务来处理单独线程中的事件。SwingWorker是一个实现Runnable的抽象类,可以定义一个任务来扩展SwingWorker,使用任务产生的结果来运行费时的任务并更新GUI。
#doInBackground():T //执行任务并返回T类型的结果#done():void //结束doInBackground之后执行事件分发线程+execute():void //安排这个SwingWorker来执行工作线程+get():T //如果有必要则等待计算完成,然后获取它的结果(即doInBackground返回的结果)+isDone():boolean //如果任务完成则返回true+cancle():beelean //取消任务#publish(data v...):void //发送process方法要处理的数据。这个方法用于从doInBackground中传送之间结果, //以处理process方法中的事件分发线程。注意,v...表示变种参数#process(data:java.util.List<V>):void //异步地接受事件分发线程上来自publish方法的数据#setProgress(progress:int):void //设置进展约束属性。这个值应该从0到100#getProgress():void //返回进展约束属性
SwingWorker有两个参数即SwingWorker< T,V>,T是doInBackground和get方法的返回类型;V是publish和process方法要处理的数据类型
完成后台线程的计算可能需要很长的时间,最好能通知用户计算的进度,可以使用JProgressBar来显示进度。考虑例子:让用户指定素数的个数n,并显示从2开始的前n个素数。代码如下:
import java.awt.BorderLayout;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.beans.PropertyChangeEvent;import java.beans.PropertyChangeListener;import java.util.List;import javax.swing.JApplet;import javax.swing.JButton;import javax.swing.JLabel;import javax.swing.JPanel;import javax.swing.JProgressBar;import javax.swing.JScrollPane;import javax.swing.JTextArea;import javax.swing.JTextField;import javax.swing.SwingWorker;public class ProgressBarDemo extends JApplet { /** * */ private static final long serialVersionUID = 1L; private JProgressBar jpb = new JProgressBar(); //定义一个进度条显示进度 private JTextArea jtaResult = new JTextArea(); //定义一个文本域显示素数 private JTextField jtfPrimeCount = new JTextField(8); //定义一个文本框用于用户填写素数个数 private JButton jbtnDisplayPrime = new JButton("Display Prime"); //定义一个按钮执行任务 public ProgressBarDemo() { jpb.setStringPainted(true); //设置显示进度的百分比 jpb.setValue(0); jpb.setMaximum(100); //设置文本域自动换行,并且断行不断字 jtaResult.setWrapStyleWord(true); jtaResult.setLineWrap(true); JPanel panel = new JPanel(); panel.add(new JLabel("Enter the prime number count")); panel.add(jtfPrimeCount); panel.add(jbtnDisplayPrime); add(jpb, BorderLayout.NORTH); add(new JScrollPane(jtaResult), BorderLayout.CENTER); add(panel, BorderLayout.SOUTH); jbtnDisplayPrime.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { ComputePrime task = new ComputePrime(Integer.parseInt(jtfPrimeCount.getText()), jtaResult); task.addPropertyChangeListener(new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { //判断改变的属性是否是进度,如果是则获取进度的值并显示在进度条上 if("progress".equals(evt.getPropertyName())) { jpb.setValue((Integer)evt.getNewValue()); } } }); task.execute(); //执行 } }); } static class ComputePrime extends SwingWorker<Integer, Integer> { private int count; private JTextArea result; public ComputePrime(int count, JTextArea result) { this.count = count; this.result = result; } @Override protected Integer doInBackground() throws Exception { publishPrimeNumbers(count); return 0; } //把找到的素数全部显示出来 @Override protected void process(List<Integer> list) { for(int i=0; i<list.size(); i++) { result.append(list.get(i) + " "); } super.process(list); } private void publishPrimeNumbers(int n) { int count = 0; int number = 2; while(count <= n) { if(isPrime(number)) { count ++; setProgress(100 * count / n); //设置进度 publish(number); //通过publish方法将找到的素数number发送给process方法 } number ++; } } public static boolean isPrime(int number) { for(int divisor = 2; divisor <= number / 2; divisor++) { if(number % divisor == 0) { return false; } } return true; } }}
注:doInBackground方法作为任务线程的一部分执行,它负责完成线程的基本任务,并以返回值来作为线程的执行结果。继承类须覆盖该方法并确保包含或代理任务线程的基本任务。不要直接调用该方法,应使用任务对象的execute方法来调度执行。
当从任务线程调用publish方法时,SwingWorker类调度process方法,如果SwingWorker通过publish发布了一些数据,那么也应该实现process方法来处理这些中间结果,任务对象的父类会在事件分发线程上激活process方法,因此在此方法中程序可以安全的更新UI组件。
无论何时调用setProgress方法,SwingWorker类都会产生一个propertyChangeEvent。setProgress方法设置一个0到100之间的新的进度值,这个值包装在PropertyChangeEvent中,这个事件的监听器使用getNewValue()方法获取进度值。
程序执行结果如下:
- java学习之浅谈多线程4--SwingWorker
- java学习之浅谈多线程1
- java SwingWorker
- java-swingworker
- java学习之浅谈多线程2--线程同步
- java学习之浅谈多线程3--线程间协作
- Java学习笔记—浅谈多线程
- 浅谈java多线程之创建线程方式
- 使用SwingWorker之二
- 使用SwingWorker之三
- 使用SwingWorker之二
- 使用SwingWorker之三
- 使用SwingWorker之二
- 使用SwingWorker之三
- 使用SwingWorker之二
- 使用SwingWorker之三
- java--------学习之《多线程》
- java学习之---多线程
- 数据结构_括号匹配
- SimpleDateFormat并发问题解决方案
- VIII.1 INS-30510: Insufficient number of ASM disks selected.
- 九度考研真题 浙大 2005-3浙大1012:畅通工程
- 数据结构_数组
- java学习之浅谈多线程4--SwingWorker
- 视频框架 Vitamio 使用教程+部分心得 (二)第一个视频demo
- Java编程思想重点笔记(Java开发必看)
- java集合的特点
- 九度考研真题 浙大 2006-1浙大1015:还是A+B 比较
- 三分钟学会JUnit单元测试
- QImage的显示
- bash 判断进程是否运行
- __FUNCTION__, __func__, __PRETTY_FUNCTION__