SwingWorker解析

作者: 落日柳风 | 来源:发表于2017-10-30 07:24 被阅读11次

    一      线程类别及为什么要使用SwingWorker

    1.1一个Swing开发人员将会和以下几种线程打交道

    初始线程:在标准的程序中,只有一个这样的线程:这个线程将调用程序主类中的main方法。在Swing程序中,初始线程主要作用是创建GUI,通过EventQueue的invokeLater方法或者invokeAndWait方法

    EventQueue.invokeLater(newRunnable()) {

    publicvoidrun() {

    createAndShowGUI();

    }}

    事件分派线程(Event dipatch thread   EDT):根据单一线程规则,所有的接触Swing组件的代码必须在该线程执行。在该线程执行的事件必须是要能快速完成的,否则事件堆积起来将造成界面响应过慢。

    工作线程:通常执行所有消耗时间的任务。

    1.2   事件分派线程与工作线程:

    这些约束意味着需要耗时操作的 GUI 应用程序至少需要以下两个线程:

    1) 执行长时间任务的工作线程;

     2) 所有 GUI 相关活动的事件指派线程 (EDT)这涉及到难以实现的线程间通信。

    SwingWorker 设计用于需要在后台线程中运行长时间运行任务的情况,并可在完成后或者在处理过程中向 UI 提供更新。SwingWorker 的子类必须实现 doInBackground() 方法,以执行后台计算。(当然也可以采用启动新线程完成耗时任务,但此时应该在线程中使用EventQueue.invokeLater方法来更新用户界面,步骤较为繁琐)

    二    使用SwingWorker

    2.1   后台任务的典型UI活动:

    1)工作过程中更新UI显示进度

    2)工作完成后做最后的更新

    2.2  工作流

    工作流

    SwingWorker 的生命周期中包含三个线程:

    当前线程:在此线程上调用 execute() 方法。它调度 SwingWorker 以在 worker 线程上执行并立即返回。可以使用 get 方法等待 SwingWorker 完成。

    Worker 线程:在此线程上调用 doInBackground() 方法。所有后台活动都应该在此线程上发生。要通知 PropertyChangeListeners 有关绑定 (bound) 属性的更改,请使用 firePropertyChange 和 getPropertyChangeSupport() 方法。默认情况下,有两个可用的绑定属性:state 和 progress。

    事件指派线程:所有与 Swing 有关的活动都在此线程上发生。SwingWorker 调用 process 和 done() 方法,并通知此线程的所有 PropertyChangeListener。

    通常,当前 线程就是事件指派线程。

    在 worker 线程上调用 doInBackground 方法之前,SwingWorker 通知所有 PropertyChangeListener 有关对 StateValue.STARTED 的 state 属性更改。doInBackground 方法完成后,执行 done 方法。然后 SwingWorker 通知所有 PropertyChangeListener 有关对 StateValue.DONE 的 state 属性更改。

    SwingWorker 被设计为只执行一次。多次执行 SwingWorker 将不会调用两次 doInBackground 方法。

    2.3   具体使用方法

    1   实现SwingWorker的子类  //该类为泛型类,产生类型为T的工作结果和类型为V的进度数据

    需要重写的方法

    doInBackground();  // 运行在工作线程中,编写执行耗时操作的逻辑代码,并以返回值来作为线程的执行结果。应在此方法中不时地调用publish()方法报告工作进度,几个publish()的调用会引起process()方法的一次调用成批处理

    process();     //运行在EDT中,接收一个包含几个中间结果的列表,从列表中提取出数据可直接用于更新UI(通常process仅仅关注每次返回的最后一组值,使用  它来更新GUI):

    done();   // 运行在EDT中,任务完成后自动调用,典型地可以使用get()方法得到工作结果数据,对UI进行最后的更新

    注意:必须要重写的方法只有doInBackground

     2   实例化该子类,调用其execute方法启动该线程

    2.4      类SwingWorker类 SwingWorker详解

    java.lang.Object

    继承者 javax.swing.SwingWorker

    类型参数:

    T - 此 SwingWorker 的doInBackground 和 get 方法返回的结果类型

    V - 用于保存此 SwingWorker 的 publish 和 process 方法的中间结果的类型

    所有已实现的接口:

    Runnable, Future, RunnableFuture(前两个接口的简单封装)

    因为实现了Runnable,所以有run方法,调用FutureTask.run()

    因为实现了Future,所以有:

    2.5   绑定属性和状态方法

    SwingWorker支持bound properties,这个在与其他线程通信时很有作用。提供两个绑定属性:progress 和 state。progress和state可以用于触发在事件派发线程中的事件处理任务。

    通过实现一个PropertyChangeListener,程序可以捕捉到progress,state或其他绑定属性的变化。

    以下为相关的方法解读:

    void addPropertyChangeListener(PropertyChangeListener listener)//通常使用匿名类的做法,任务子类的方法

    将PropertyChangeListener添加到侦听器列表。

    void firePropertyChange(StringpropertyName,Object oldValue, Object newValue)

    向所有已注册的侦听器报告绑定属性更新

    int getProgress()

    返回progress绑定属性。

    PropertyChangeSupport getPropertyChangeSupport()

    返回此SwingWorker的PropertyChangeSupport。

    protected  void setProgress(int progress)

    设置progress绑定属性。

    典例:使用ProgressBar更新显示进度,很方便地在工作线程与EDT之间进行通信

    setProgress(100 * numbers.size() / numbersToFind);

    task.addPropertyChangeListener(new PropertyChangeListener() {

    public  void propertyChange(PropertyChangeEvent evt) //需要重写的方法

    {

    if ("progress".equals(evt.getPropertyName()))//得到属性的名称

    {

    progressBar.setValue((Integer)evt.getNewValue())//得到属性最新对应的值;         

       }

    }});

    更多关于SwingWorker方法的解析:http://www.oschina.net/uploads/doc/javase-6-doc-api-zh_CN/javax/swing/SwingWorker.html

    相关文章

      网友评论

        本文标题:SwingWorker解析

        本文链接:https://www.haomeiwen.com/subject/cyaupxtx.html