Java界面中使用SwingWorker

时间:2023-01-28 00:12:37

Java Swing GUI程序启动时,JVM会启动多个线程,Swing并不是线程安全的,如果处理不当Swing程序会反应迟钝,JavaSE6开始引用SwingWorker能够改善Swing程序结构,提高界面的灵活性。

  • 事件派发线程

    当界面程序启动时,会调用界面的主方法

     
    Java.awt.EventQueue.invokeLater(new Runnable(){
    public void run(){
    new NumberAddutionUI().setVisible(true);
    }
    }

    invoketLater方法的意思是提交程序在事件派发线程(EDT)上执行其Runnable任务,此点是创建UI的点,也就是线程开始将控制权转交给UI的点。之后,主线程结束,程序在EDT中运行。由于EDT线程负责GUI组件的绘制和更新,所有事件处理都在EDT上进行,程序同UI组件和其基本数据的交互只允许在EDT上进行。由此可知EDT队列非常繁忙,几乎每一次GUI交互和事件都是通过它完成的。所以事件队列中的任务必须非常快,否则就会阻塞其他任务。因此,所有耗时的任务都不应该放在EDT上进行,同时Swing编程也要注意以下几点,

     1)从非EDT线程访问UI主键及其事件监听器会废纸界面更新和绘制错误。

     2)从EDT上执行耗时任务线程会使程序失去响应,这会使GUI事件阻塞在队列中得不到处理。

     3) 应使用独立的任务线程来执行耗时计算或输入输出密集型任务,想数据库通信,访问网站资源,读写大量数据的文件。

    总之任何干好活延迟UI事件处理只应该在独立任务线程中;在主线程或任务线程中同Swing组件或其默认数据模式进行的交互都是非线程安全的。

  • SwingWorker类

    • SwingWorker类的定义

      Swing Worker类能够帮助线程与Swing EDT之间的交互,有助于分离Swing EDT和任务线程。SwingWorker的使用能够使他们各负其责,对于EDT来说,就是绘制和更新界面,并响应用户输入;对于线程任务来说,就是执行和界面无直接关系的耗时任务和I/O密集型操作。

      SwingWorker类的定义
      当界面程序启动时,会调用界面的主方法

           public abstract calss SwingWorker<T,V>
      extends Object implements RunnableFuture

      SwingWorker是抽象类,因此必须继承它才能执行所需的特定任务。该类对象产生类型为T的结果值以及类型为V的进度数据。

      RunnableFuture是Runnable和Future两个接口的简单封装。

      SwingWorker实现了两个父类接口大部分方法。

      方法 功能
      boolean cancel(boolean mayInterruptIfRunning) 取消正在进行的工作。
      T get() 获取类型为T的结果值。该方法将一直处于阻塞状态,直到结果可用。
      T get(long timeout,TimeUnit unit) 获取类型为T的结果值,将会一直阻塞直到结果可用或超时。
      boolean isCancelled() 判断任务线程是否被取消。
      boolean isDone() 判断任务线程是否完成。
      abstract T doInBackground() 该方法作为线程的一部分执行,负责完成线程的基本任务,并以返回值(类型为T)作为线程的执行结果。继承类必须覆盖该方法并确保包含或代理任务线程的基本任务。不要直接调用该方法,应使任务对象的execute方法来调度执行。
      protected void done() 在doInBackground()方法完成之后,SwingWorker在EDT上激活done方法。如果任务需要在完成后使用线程结果更新GUI组件或者做些清理工作,可覆盖该方法来完成.
      void publish(V…data) 传递中间进度数据到EDT。从doInBankground方法调用该方法。
      void process(Listdata) 覆盖该方法处理任务线程的中间结果数据
      void execute() 为SwingWorker线程的执行预订这个SwingWorker对象。

      任务线程有几种状态:使用SwingWorker.StateValue枚举值来表示:PENDING、STARTED和DONE线程一旦创建就处于PENDING 状态,当doInBackground方法开始时,任务就进入STARTED状态,当doInBackground方法完成后,任务线程就出入DONE状态
      任务对象有一个进度属性,随着任务进展时,可以将这个属性从0更新到100标识任务进度,当该属性发生变化时,任务通知处理器进行处理。

    • SwingWorker的工作模式

      当Swing GUI 程序执行耗时任务时,在EDT中创建一个SwingWorker对象。在该对象编写有实现耗时任务代码的doInBackground方法中执行耗时操作,该方法在EDT中被使用execute方法调用,在SwingWorker线程中执行。在doInBackground方法中不时地调用public来发布中间数据。publish方法使得process方法在EDT中执行来处理进度数据。当工作完成时,在EDT中调用done方法以便完成UI的更新,在done方法中可以用get方法获取doInBackground的执行结果

      Java界面中使用SwingWorker